Quellcodebibliothek Statistik Leitseite products/sources/formale Sprachen/C/Linux/drivers/platform/chrome/   (Open Source Betriebssystem Version 6.17.9©)  Datei vom 24.10.2025 mit Größe 82 kB image not shown  

Quelle  cros_ec_proto_test.c   Sprache: C

 
// SPDX-License-Identifier: GPL-2.0
/*
 * Kunit tests for ChromeOS Embedded Controller protocol.
 */


#include <kunit/test.h>

#include <linux/unaligned.h>

#include <linux/platform_data/cros_ec_commands.h>
#include <linux/platform_data/cros_ec_proto.h>

#include "cros_ec.h"
#include "cros_ec_proto_test_util.h"

#define BUFSIZE 512

struct cros_ec_proto_test_priv {
 struct cros_ec_device ec_dev;
 u8 dout[BUFSIZE];
 u8 din[BUFSIZE];
 struct cros_ec_command *msg;
 u8 _msg[BUFSIZE];
};

static void cros_ec_proto_test_prepare_tx_legacy_normal(struct kunit *test)
{
 struct cros_ec_proto_test_priv *priv = test->priv;
 struct cros_ec_device *ec_dev = &priv->ec_dev;
 struct cros_ec_command *msg = priv->msg;
 int ret, i;
 u8 csum;

 ec_dev->proto_version = 2;

 msg->command = EC_CMD_HELLO;
 msg->outsize = EC_PROTO2_MAX_PARAM_SIZE;
 msg->data[0] = 0xde;
 msg->data[1] = 0xad;
 msg->data[2] = 0xbe;
 msg->data[3] = 0xef;

 ret = cros_ec_prepare_tx(ec_dev, msg);

 KUNIT_EXPECT_EQ(test, ret, EC_MSG_TX_PROTO_BYTES + EC_PROTO2_MAX_PARAM_SIZE);
 KUNIT_EXPECT_EQ(test, ec_dev->dout[0], EC_CMD_VERSION0);
 KUNIT_EXPECT_EQ(test, ec_dev->dout[1], EC_CMD_HELLO);
 KUNIT_EXPECT_EQ(test, ec_dev->dout[2], EC_PROTO2_MAX_PARAM_SIZE);
 KUNIT_EXPECT_EQ(test, EC_MSG_TX_HEADER_BYTES, 3);
 KUNIT_EXPECT_EQ(test, ec_dev->dout[EC_MSG_TX_HEADER_BYTES + 0], 0xde);
 KUNIT_EXPECT_EQ(test, ec_dev->dout[EC_MSG_TX_HEADER_BYTES + 1], 0xad);
 KUNIT_EXPECT_EQ(test, ec_dev->dout[EC_MSG_TX_HEADER_BYTES + 2], 0xbe);
 KUNIT_EXPECT_EQ(test, ec_dev->dout[EC_MSG_TX_HEADER_BYTES + 3], 0xef);
 for (i = 4; i < EC_PROTO2_MAX_PARAM_SIZE; ++i)
  KUNIT_EXPECT_EQ(test, ec_dev->dout[EC_MSG_TX_HEADER_BYTES + i], 0);

 csum = EC_CMD_VERSION0;
 csum += EC_CMD_HELLO;
 csum += EC_PROTO2_MAX_PARAM_SIZE;
 csum += 0xde;
 csum += 0xad;
 csum += 0xbe;
 csum += 0xef;
 KUNIT_EXPECT_EQ(test,
   ec_dev->dout[EC_MSG_TX_HEADER_BYTES + EC_PROTO2_MAX_PARAM_SIZE],
   csum);
}

static void cros_ec_proto_test_prepare_tx_legacy_bad_msg_outsize(struct kunit *test)
{
 struct cros_ec_proto_test_priv *priv = test->priv;
 struct cros_ec_device *ec_dev = &priv->ec_dev;
 struct cros_ec_command *msg = priv->msg;
 int ret;

 ec_dev->proto_version = 2;

 msg->outsize = EC_PROTO2_MAX_PARAM_SIZE + 1;

 ret = cros_ec_prepare_tx(ec_dev, msg);
 KUNIT_EXPECT_EQ(test, ret, -EINVAL);
}

static void cros_ec_proto_test_prepare_tx_normal(struct kunit *test)
{
 struct cros_ec_proto_test_priv *priv = test->priv;
 struct cros_ec_device *ec_dev = &priv->ec_dev;
 struct cros_ec_command *msg = priv->msg;
 struct ec_host_request *request = (struct ec_host_request *)ec_dev->dout;
 int ret, i;
 u8 csum;

 msg->command = EC_CMD_HELLO;
 msg->outsize = 0x88;
 msg->data[0] = 0xde;
 msg->data[1] = 0xad;
 msg->data[2] = 0xbe;
 msg->data[3] = 0xef;

 ret = cros_ec_prepare_tx(ec_dev, msg);

 KUNIT_EXPECT_EQ(test, ret, sizeof(*request) + 0x88);

 KUNIT_EXPECT_EQ(test, request->struct_version, EC_HOST_REQUEST_VERSION);
 KUNIT_EXPECT_EQ(test, request->command, EC_CMD_HELLO);
 KUNIT_EXPECT_EQ(test, request->command_version, 0);
 KUNIT_EXPECT_EQ(test, request->data_len, 0x88);
 KUNIT_EXPECT_EQ(test, ec_dev->dout[sizeof(*request) + 0], 0xde);
 KUNIT_EXPECT_EQ(test, ec_dev->dout[sizeof(*request) + 1], 0xad);
 KUNIT_EXPECT_EQ(test, ec_dev->dout[sizeof(*request) + 2], 0xbe);
 KUNIT_EXPECT_EQ(test, ec_dev->dout[sizeof(*request) + 3], 0xef);
 for (i = 4; i < 0x88; ++i)
  KUNIT_EXPECT_EQ(test, ec_dev->dout[sizeof(*request) + i], 0);

 csum = EC_HOST_REQUEST_VERSION;
 csum += EC_CMD_HELLO;
 csum += 0x88;
 csum += 0xde;
 csum += 0xad;
 csum += 0xbe;
 csum += 0xef;
 KUNIT_EXPECT_EQ(test, request->checksum, (u8)-csum);
}

static void cros_ec_proto_test_prepare_tx_bad_msg_outsize(struct kunit *test)
{
 struct cros_ec_proto_test_priv *priv = test->priv;
 struct cros_ec_device *ec_dev = &priv->ec_dev;
 struct cros_ec_command *msg = priv->msg;
 int ret;

 msg->outsize = ec_dev->dout_size - sizeof(struct ec_host_request) + 1;

 ret = cros_ec_prepare_tx(ec_dev, msg);
 KUNIT_EXPECT_EQ(test, ret, -EINVAL);
}

static void cros_ec_proto_test_check_result(struct kunit *test)
{
 struct cros_ec_proto_test_priv *priv = test->priv;
 struct cros_ec_device *ec_dev = &priv->ec_dev;
 struct cros_ec_command *msg = priv->msg;
 int ret, i;
 static enum ec_status status[] = {
  EC_RES_SUCCESS,
  EC_RES_INVALID_COMMAND,
  EC_RES_ERROR,
  EC_RES_INVALID_PARAM,
  EC_RES_ACCESS_DENIED,
  EC_RES_INVALID_RESPONSE,
  EC_RES_INVALID_VERSION,
  EC_RES_INVALID_CHECKSUM,
  EC_RES_UNAVAILABLE,
  EC_RES_TIMEOUT,
  EC_RES_OVERFLOW,
  EC_RES_INVALID_HEADER,
  EC_RES_REQUEST_TRUNCATED,
  EC_RES_RESPONSE_TOO_BIG,
  EC_RES_BUS_ERROR,
  EC_RES_BUSY,
  EC_RES_INVALID_HEADER_VERSION,
  EC_RES_INVALID_HEADER_CRC,
  EC_RES_INVALID_DATA_CRC,
  EC_RES_DUP_UNAVAILABLE,
 };

 for (i = 0; i < ARRAY_SIZE(status); ++i) {
  msg->result = status[i];
  ret = cros_ec_check_result(ec_dev, msg);
  KUNIT_EXPECT_EQ(test, ret, 0);
 }

 msg->result = EC_RES_IN_PROGRESS;
 ret = cros_ec_check_result(ec_dev, msg);
 KUNIT_EXPECT_EQ(test, ret, -EAGAIN);
}

static void cros_ec_proto_test_query_all_pretest(struct kunit *test)
{
 struct cros_ec_proto_test_priv *priv = test->priv;
 struct cros_ec_device *ec_dev = &priv->ec_dev;

 /*
 * cros_ec_query_all() will free din and dout and allocate them again to fit the usage by
 * calling devm_kfree() and devm_kzalloc().  Set them to NULL as they aren't managed by
 * ec_dev->dev but allocated statically in struct cros_ec_proto_test_priv
 * (see cros_ec_proto_test_init()).
 */

 ec_dev->din = NULL;
 ec_dev->dout = NULL;
}

static void cros_ec_proto_test_query_all_normal(struct kunit *test)
{
 struct cros_ec_proto_test_priv *priv = test->priv;
 struct cros_ec_device *ec_dev = &priv->ec_dev;
 struct ec_xfer_mock *mock;
 int ret;

 /* For cros_ec_get_proto_info() without passthru. */
 {
  struct ec_response_get_protocol_info *data;

  mock = cros_kunit_ec_xfer_mock_add(test, sizeof(*data));
  KUNIT_ASSERT_PTR_NE(test, mock, NULL);

  data = (struct ec_response_get_protocol_info *)mock->o_data;
  data->protocol_versions = BIT(3) | BIT(2);
  data->max_request_packet_size = 0xbe;
  data->max_response_packet_size = 0xef;
 }

 /* For cros_ec_get_proto_info() with passthru. */
 {
  struct ec_response_get_protocol_info *data;

  mock = cros_kunit_ec_xfer_mock_add(test, sizeof(*data));
  KUNIT_ASSERT_PTR_NE(test, mock, NULL);

  data = (struct ec_response_get_protocol_info *)mock->o_data;
  data->max_request_packet_size = 0xbf;
 }

 /* For cros_ec_get_host_command_version_mask() for MKBP. */
 {
  struct ec_response_get_cmd_versions *data;

  mock = cros_kunit_ec_xfer_mock_add(test, sizeof(*data));
  KUNIT_ASSERT_PTR_NE(test, mock, NULL);

  data = (struct ec_response_get_cmd_versions *)mock->o_data;
  data->version_mask = BIT(6) | BIT(5);
 }

 /* For cros_ec_get_host_command_version_mask() for host sleep v1. */
 {
  struct ec_response_get_cmd_versions *data;

  mock = cros_kunit_ec_xfer_mock_add(test, sizeof(*data));
  KUNIT_ASSERT_PTR_NE(test, mock, NULL);

  data = (struct ec_response_get_cmd_versions *)mock->o_data;
  data->version_mask = BIT(1);
 }

 /* For cros_ec_get_host_event_wake_mask(). */
 {
  struct ec_response_host_event_mask *data;

  mock = cros_kunit_ec_xfer_mock_add(test, sizeof(*data));
  KUNIT_ASSERT_PTR_NE(test, mock, NULL);

  data = (struct ec_response_host_event_mask *)mock->o_data;
  data->mask = 0xbeef;
 }

 cros_ec_proto_test_query_all_pretest(test);
 ret = cros_ec_query_all(ec_dev);
 KUNIT_EXPECT_EQ(test, ret, 0);

 /* For cros_ec_get_proto_info() without passthru. */
 {
  mock = cros_kunit_ec_xfer_mock_next();
  KUNIT_EXPECT_PTR_NE(test, mock, NULL);

  KUNIT_EXPECT_EQ(test, mock->msg.version, 0);
  KUNIT_EXPECT_EQ(test, mock->msg.command, EC_CMD_GET_PROTOCOL_INFO);
  KUNIT_EXPECT_EQ(test, mock->msg.insize,
    sizeof(struct ec_response_get_protocol_info));
  KUNIT_EXPECT_EQ(test, mock->msg.outsize, 0);

  KUNIT_EXPECT_EQ(test, ec_dev->max_request, 0xbe - sizeof(struct ec_host_request));
  KUNIT_EXPECT_EQ(test, ec_dev->max_response, 0xef - sizeof(struct ec_host_response));
  KUNIT_EXPECT_EQ(test, ec_dev->proto_version, 3);
  KUNIT_EXPECT_EQ(test, ec_dev->din_size, 0xef + EC_MAX_RESPONSE_OVERHEAD);
  KUNIT_EXPECT_EQ(test, ec_dev->dout_size, 0xbe + EC_MAX_REQUEST_OVERHEAD);
 }

 /* For cros_ec_get_proto_info() with passthru. */
 {
  mock = cros_kunit_ec_xfer_mock_next();
  KUNIT_EXPECT_PTR_NE(test, mock, NULL);

  KUNIT_EXPECT_EQ(test, mock->msg.version, 0);
  KUNIT_EXPECT_EQ(test, mock->msg.command,
    EC_CMD_PASSTHRU_OFFSET(CROS_EC_DEV_PD_INDEX) |
    EC_CMD_GET_PROTOCOL_INFO);
  KUNIT_EXPECT_EQ(test, mock->msg.insize,
    sizeof(struct ec_response_get_protocol_info));
  KUNIT_EXPECT_EQ(test, mock->msg.outsize, 0);

  KUNIT_EXPECT_EQ(test, ec_dev->max_passthru, 0xbf - sizeof(struct ec_host_request));
 }

 /* For cros_ec_get_host_command_version_mask() for MKBP. */
 {
  struct ec_params_get_cmd_versions *data;

  mock = cros_kunit_ec_xfer_mock_next();
  KUNIT_EXPECT_PTR_NE(test, mock, NULL);

  KUNIT_EXPECT_EQ(test, mock->msg.version, 0);
  KUNIT_EXPECT_EQ(test, mock->msg.command, EC_CMD_GET_CMD_VERSIONS);
  KUNIT_EXPECT_EQ(test, mock->msg.insize,
    sizeof(struct ec_response_get_cmd_versions));
  KUNIT_EXPECT_EQ(test, mock->msg.outsize, sizeof(*data));

  data = (struct ec_params_get_cmd_versions *)mock->i_data;
  KUNIT_EXPECT_EQ(test, data->cmd, EC_CMD_GET_NEXT_EVENT);

  KUNIT_EXPECT_EQ(test, ec_dev->mkbp_event_supported, 7);
 }

 /* For cros_ec_get_host_command_version_mask() for host sleep v1. */
 {
  struct ec_params_get_cmd_versions *data;

  mock = cros_kunit_ec_xfer_mock_next();
  KUNIT_EXPECT_PTR_NE(test, mock, NULL);

  KUNIT_EXPECT_EQ(test, mock->msg.version, 0);
  KUNIT_EXPECT_EQ(test, mock->msg.command, EC_CMD_GET_CMD_VERSIONS);
  KUNIT_EXPECT_EQ(test, mock->msg.insize,
    sizeof(struct ec_response_get_cmd_versions));
  KUNIT_EXPECT_EQ(test, mock->msg.outsize, sizeof(*data));

  data = (struct ec_params_get_cmd_versions *)mock->i_data;
  KUNIT_EXPECT_EQ(test, data->cmd, EC_CMD_HOST_SLEEP_EVENT);

  KUNIT_EXPECT_TRUE(test, ec_dev->host_sleep_v1);
 }

 /* For cros_ec_get_host_event_wake_mask(). */
 {
  mock = cros_kunit_ec_xfer_mock_next();
  KUNIT_EXPECT_PTR_NE(test, mock, NULL);

  KUNIT_EXPECT_EQ(test, mock->msg.version, 0);
  KUNIT_EXPECT_EQ(test, mock->msg.command, EC_CMD_HOST_EVENT_GET_WAKE_MASK);
  KUNIT_EXPECT_EQ(test, mock->msg.insize, sizeof(struct ec_response_host_event_mask));
  KUNIT_EXPECT_EQ(test, mock->msg.outsize, 0);

  KUNIT_EXPECT_EQ(test, ec_dev->host_event_wake_mask, 0xbeef);
 }
}

static void cros_ec_proto_test_query_all_no_pd_return_error(struct kunit *test)
{
 struct cros_ec_proto_test_priv *priv = test->priv;
 struct cros_ec_device *ec_dev = &priv->ec_dev;
 struct ec_xfer_mock *mock;
 int ret;

 /* Set some garbage bytes. */
 ec_dev->max_passthru = 0xbf;

 /* For cros_ec_get_proto_info() without passthru. */
 {
  struct ec_response_get_protocol_info *data;

  mock = cros_kunit_ec_xfer_mock_add(test, sizeof(*data));
  KUNIT_ASSERT_PTR_NE(test, mock, NULL);

  /*
 * Although it doesn't check the value, provides valid sizes so that
 * cros_ec_query_all() allocates din and dout correctly.
 */

  data = (struct ec_response_get_protocol_info *)mock->o_data;
  data->max_request_packet_size = 0xbe;
  data->max_response_packet_size = 0xef;
 }

 /* For cros_ec_get_proto_info() with passthru. */
 {
  mock = cros_kunit_ec_xfer_mock_addx(test, 0, EC_RES_INVALID_COMMAND, 0);
  KUNIT_ASSERT_PTR_NE(test, mock, NULL);
 }

 cros_ec_proto_test_query_all_pretest(test);
 ret = cros_ec_query_all(ec_dev);
 KUNIT_EXPECT_EQ(test, ret, 0);

 /* For cros_ec_get_proto_info() without passthru. */
 {
  mock = cros_kunit_ec_xfer_mock_next();
  KUNIT_EXPECT_PTR_NE(test, mock, NULL);

  KUNIT_EXPECT_EQ(test, mock->msg.version, 0);
  KUNIT_EXPECT_EQ(test, mock->msg.command, EC_CMD_GET_PROTOCOL_INFO);
  KUNIT_EXPECT_EQ(test, mock->msg.insize,
    sizeof(struct ec_response_get_protocol_info));
  KUNIT_EXPECT_EQ(test, mock->msg.outsize, 0);
 }

 /* For cros_ec_get_proto_info() with passthru. */
 {
  mock = cros_kunit_ec_xfer_mock_next();
  KUNIT_EXPECT_PTR_NE(test, mock, NULL);

  KUNIT_EXPECT_EQ(test, mock->msg.version, 0);
  KUNIT_EXPECT_EQ(test, mock->msg.command,
    EC_CMD_PASSTHRU_OFFSET(CROS_EC_DEV_PD_INDEX) |
    EC_CMD_GET_PROTOCOL_INFO);
  KUNIT_EXPECT_EQ(test, mock->msg.insize,
    sizeof(struct ec_response_get_protocol_info));
  KUNIT_EXPECT_EQ(test, mock->msg.outsize, 0);

  KUNIT_EXPECT_EQ(test, ec_dev->max_passthru, 0);
 }
}

static void cros_ec_proto_test_query_all_no_pd_return0(struct kunit *test)
{
 struct cros_ec_proto_test_priv *priv = test->priv;
 struct cros_ec_device *ec_dev = &priv->ec_dev;
 struct ec_xfer_mock *mock;
 int ret;

 /* Set some garbage bytes. */
 ec_dev->max_passthru = 0xbf;

 /* For cros_ec_get_proto_info() without passthru. */
 {
  struct ec_response_get_protocol_info *data;

  mock = cros_kunit_ec_xfer_mock_add(test, sizeof(*data));
  KUNIT_ASSERT_PTR_NE(test, mock, NULL);

  /*
 * Although it doesn't check the value, provides valid sizes so that
 * cros_ec_query_all() allocates din and dout correctly.
 */

  data = (struct ec_response_get_protocol_info *)mock->o_data;
  data->max_request_packet_size = 0xbe;
  data->max_response_packet_size = 0xef;
 }

 /* For cros_ec_get_proto_info() with passthru. */
 {
  mock = cros_kunit_ec_xfer_mock_add(test, 0);
  KUNIT_ASSERT_PTR_NE(test, mock, NULL);
 }

 cros_ec_proto_test_query_all_pretest(test);
 ret = cros_ec_query_all(ec_dev);
 KUNIT_EXPECT_EQ(test, ret, 0);

 /* For cros_ec_get_proto_info() without passthru. */
 {
  mock = cros_kunit_ec_xfer_mock_next();
  KUNIT_EXPECT_PTR_NE(test, mock, NULL);

  KUNIT_EXPECT_EQ(test, mock->msg.version, 0);
  KUNIT_EXPECT_EQ(test, mock->msg.command, EC_CMD_GET_PROTOCOL_INFO);
  KUNIT_EXPECT_EQ(test, mock->msg.insize,
    sizeof(struct ec_response_get_protocol_info));
  KUNIT_EXPECT_EQ(test, mock->msg.outsize, 0);
 }

 /* For cros_ec_get_proto_info() with passthru. */
 {
  mock = cros_kunit_ec_xfer_mock_next();
  KUNIT_EXPECT_PTR_NE(test, mock, NULL);

  KUNIT_EXPECT_EQ(test, mock->msg.version, 0);
  KUNIT_EXPECT_EQ(test, mock->msg.command,
    EC_CMD_PASSTHRU_OFFSET(CROS_EC_DEV_PD_INDEX) |
    EC_CMD_GET_PROTOCOL_INFO);
  KUNIT_EXPECT_EQ(test, mock->msg.insize,
    sizeof(struct ec_response_get_protocol_info));
  KUNIT_EXPECT_EQ(test, mock->msg.outsize, 0);

  KUNIT_EXPECT_EQ(test, ec_dev->max_passthru, 0);
 }
}

static void cros_ec_proto_test_query_all_legacy_normal_v3_return_error(struct kunit *test)
{
 struct cros_ec_proto_test_priv *priv = test->priv;
 struct cros_ec_device *ec_dev = &priv->ec_dev;
 struct ec_xfer_mock *mock;
 int ret;

 /* For cros_ec_get_proto_info() without passthru. */
 {
  mock = cros_kunit_ec_xfer_mock_addx(test, 0, EC_RES_INVALID_COMMAND, 0);
  KUNIT_ASSERT_PTR_NE(test, mock, NULL);
 }

 /* For cros_ec_get_proto_info_legacy(). */
 {
  struct ec_response_hello *data;

  mock = cros_kunit_ec_xfer_mock_add(test, sizeof(*data));
  KUNIT_ASSERT_PTR_NE(test, mock, NULL);

  data = (struct ec_response_hello *)mock->o_data;
  data->out_data = 0xa1b2c3d4;
 }

 cros_ec_proto_test_query_all_pretest(test);
 ret = cros_ec_query_all(ec_dev);
 KUNIT_EXPECT_EQ(test, ret, 0);

 /* For cros_ec_get_proto_info() without passthru. */
 {
  mock = cros_kunit_ec_xfer_mock_next();
  KUNIT_EXPECT_PTR_NE(test, mock, NULL);

  KUNIT_EXPECT_EQ(test, mock->msg.version, 0);
  KUNIT_EXPECT_EQ(test, mock->msg.command, EC_CMD_GET_PROTOCOL_INFO);
  KUNIT_EXPECT_EQ(test, mock->msg.insize,
    sizeof(struct ec_response_get_protocol_info));
  KUNIT_EXPECT_EQ(test, mock->msg.outsize, 0);
 }

 /* For cros_ec_get_proto_info_legacy(). */
 {
  struct ec_params_hello *data;

  mock = cros_kunit_ec_xfer_mock_next();
  KUNIT_EXPECT_PTR_NE(test, mock, NULL);

  KUNIT_EXPECT_EQ(test, mock->msg.version, 0);
  KUNIT_EXPECT_EQ(test, mock->msg.command, EC_CMD_HELLO);
  KUNIT_EXPECT_EQ(test, mock->msg.insize, sizeof(struct ec_response_hello));
  KUNIT_EXPECT_EQ(test, mock->msg.outsize, sizeof(*data));

  data = (struct ec_params_hello *)mock->i_data;
  KUNIT_EXPECT_EQ(test, data->in_data, 0xa0b0c0d0);

  KUNIT_EXPECT_EQ(test, ec_dev->proto_version, 2);
  KUNIT_EXPECT_EQ(test, ec_dev->max_request, EC_PROTO2_MAX_PARAM_SIZE);
  KUNIT_EXPECT_EQ(test, ec_dev->max_response, EC_PROTO2_MAX_PARAM_SIZE);
  KUNIT_EXPECT_EQ(test, ec_dev->max_passthru, 0);
  KUNIT_EXPECT_PTR_EQ(test, ec_dev->pkt_xfer, NULL);
  KUNIT_EXPECT_EQ(test, ec_dev->din_size, EC_PROTO2_MSG_BYTES);
  KUNIT_EXPECT_EQ(test, ec_dev->dout_size, EC_PROTO2_MSG_BYTES);
 }
}

static void cros_ec_proto_test_query_all_legacy_normal_v3_return0(struct kunit *test)
{
 struct cros_ec_proto_test_priv *priv = test->priv;
 struct cros_ec_device *ec_dev = &priv->ec_dev;
 struct ec_xfer_mock *mock;
 int ret;

 /* For cros_ec_get_proto_info() without passthru. */
 {
  mock = cros_kunit_ec_xfer_mock_add(test, 0);
  KUNIT_ASSERT_PTR_NE(test, mock, NULL);
 }

 /* For cros_ec_get_proto_info_legacy(). */
 {
  struct ec_response_hello *data;

  mock = cros_kunit_ec_xfer_mock_add(test, sizeof(*data));
  KUNIT_ASSERT_PTR_NE(test, mock, NULL);

  data = (struct ec_response_hello *)mock->o_data;
  data->out_data = 0xa1b2c3d4;
 }

 cros_ec_proto_test_query_all_pretest(test);
 ret = cros_ec_query_all(ec_dev);
 KUNIT_EXPECT_EQ(test, ret, 0);

 /* For cros_ec_get_proto_info() without passthru. */
 {
  mock = cros_kunit_ec_xfer_mock_next();
  KUNIT_EXPECT_PTR_NE(test, mock, NULL);

  KUNIT_EXPECT_EQ(test, mock->msg.version, 0);
  KUNIT_EXPECT_EQ(test, mock->msg.command, EC_CMD_GET_PROTOCOL_INFO);
  KUNIT_EXPECT_EQ(test, mock->msg.insize,
    sizeof(struct ec_response_get_protocol_info));
  KUNIT_EXPECT_EQ(test, mock->msg.outsize, 0);
 }

 /* For cros_ec_get_proto_info_legacy(). */
 {
  struct ec_params_hello *data;

  mock = cros_kunit_ec_xfer_mock_next();
  KUNIT_EXPECT_PTR_NE(test, mock, NULL);

  KUNIT_EXPECT_EQ(test, mock->msg.version, 0);
  KUNIT_EXPECT_EQ(test, mock->msg.command, EC_CMD_HELLO);
  KUNIT_EXPECT_EQ(test, mock->msg.insize, sizeof(struct ec_response_hello));
  KUNIT_EXPECT_EQ(test, mock->msg.outsize, sizeof(*data));

  data = (struct ec_params_hello *)mock->i_data;
  KUNIT_EXPECT_EQ(test, data->in_data, 0xa0b0c0d0);

  KUNIT_EXPECT_EQ(test, ec_dev->proto_version, 2);
  KUNIT_EXPECT_EQ(test, ec_dev->max_request, EC_PROTO2_MAX_PARAM_SIZE);
  KUNIT_EXPECT_EQ(test, ec_dev->max_response, EC_PROTO2_MAX_PARAM_SIZE);
  KUNIT_EXPECT_EQ(test, ec_dev->max_passthru, 0);
  KUNIT_EXPECT_PTR_EQ(test, ec_dev->pkt_xfer, NULL);
  KUNIT_EXPECT_EQ(test, ec_dev->din_size, EC_PROTO2_MSG_BYTES);
  KUNIT_EXPECT_EQ(test, ec_dev->dout_size, EC_PROTO2_MSG_BYTES);
 }
}

static void cros_ec_proto_test_query_all_legacy_xfer_error(struct kunit *test)
{
 struct cros_ec_proto_test_priv *priv = test->priv;
 struct cros_ec_device *ec_dev = &priv->ec_dev;
 struct ec_xfer_mock *mock;
 int ret;

 /* For cros_ec_get_proto_info() without passthru. */
 {
  mock = cros_kunit_ec_xfer_mock_addx(test, 0, EC_RES_INVALID_COMMAND, 0);
  KUNIT_ASSERT_PTR_NE(test, mock, NULL);
 }

 /* For cros_ec_get_proto_info_legacy(). */
 {
  mock = cros_kunit_ec_xfer_mock_addx(test, -EIO, EC_RES_SUCCESS, 0);
  KUNIT_ASSERT_PTR_NE(test, mock, NULL);
 }

 cros_ec_proto_test_query_all_pretest(test);
 ret = cros_ec_query_all(ec_dev);
 KUNIT_EXPECT_EQ(test, ret, -EIO);
 KUNIT_EXPECT_EQ(test, ec_dev->proto_version, EC_PROTO_VERSION_UNKNOWN);

 /* For cros_ec_get_proto_info() without passthru. */
 {
  mock = cros_kunit_ec_xfer_mock_next();
  KUNIT_EXPECT_PTR_NE(test, mock, NULL);

  KUNIT_EXPECT_EQ(test, mock->msg.version, 0);
  KUNIT_EXPECT_EQ(test, mock->msg.command, EC_CMD_GET_PROTOCOL_INFO);
  KUNIT_EXPECT_EQ(test, mock->msg.insize,
    sizeof(struct ec_response_get_protocol_info));
  KUNIT_EXPECT_EQ(test, mock->msg.outsize, 0);
 }

 /* For cros_ec_get_proto_info_legacy(). */
 {
  mock = cros_kunit_ec_xfer_mock_next();
  KUNIT_EXPECT_PTR_NE(test, mock, NULL);

  KUNIT_EXPECT_EQ(test, mock->msg.version, 0);
  KUNIT_EXPECT_EQ(test, mock->msg.command, EC_CMD_HELLO);
  KUNIT_EXPECT_EQ(test, mock->msg.insize, sizeof(struct ec_response_hello));
  KUNIT_EXPECT_EQ(test, mock->msg.outsize, sizeof(struct ec_params_hello));
 }
}

static void cros_ec_proto_test_query_all_legacy_return_error(struct kunit *test)
{
 struct cros_ec_proto_test_priv *priv = test->priv;
 struct cros_ec_device *ec_dev = &priv->ec_dev;
 struct ec_xfer_mock *mock;
 int ret;

 /* For cros_ec_get_proto_info() without passthru. */
 {
  mock = cros_kunit_ec_xfer_mock_addx(test, 0, EC_RES_INVALID_COMMAND, 0);
  KUNIT_ASSERT_PTR_NE(test, mock, NULL);
 }

 /* For cros_ec_get_proto_info_legacy(). */
 {
  mock = cros_kunit_ec_xfer_mock_addx(test, 0, EC_RES_INVALID_COMMAND, 0);
  KUNIT_ASSERT_PTR_NE(test, mock, NULL);
 }

 cros_ec_proto_test_query_all_pretest(test);
 ret = cros_ec_query_all(ec_dev);
 KUNIT_EXPECT_EQ(test, ret, -EOPNOTSUPP);
 KUNIT_EXPECT_EQ(test, ec_dev->proto_version, EC_PROTO_VERSION_UNKNOWN);

 /* For cros_ec_get_proto_info() without passthru. */
 {
  mock = cros_kunit_ec_xfer_mock_next();
  KUNIT_EXPECT_PTR_NE(test, mock, NULL);

  KUNIT_EXPECT_EQ(test, mock->msg.version, 0);
  KUNIT_EXPECT_EQ(test, mock->msg.command, EC_CMD_GET_PROTOCOL_INFO);
  KUNIT_EXPECT_EQ(test, mock->msg.insize,
    sizeof(struct ec_response_get_protocol_info));
  KUNIT_EXPECT_EQ(test, mock->msg.outsize, 0);
 }

 /* For cros_ec_get_proto_info_legacy(). */
 {
  mock = cros_kunit_ec_xfer_mock_next();
  KUNIT_EXPECT_PTR_NE(test, mock, NULL);

  KUNIT_EXPECT_EQ(test, mock->msg.version, 0);
  KUNIT_EXPECT_EQ(test, mock->msg.command, EC_CMD_HELLO);
  KUNIT_EXPECT_EQ(test, mock->msg.insize, sizeof(struct ec_response_hello));
  KUNIT_EXPECT_EQ(test, mock->msg.outsize, sizeof(struct ec_params_hello));
 }
}

static void cros_ec_proto_test_query_all_legacy_data_error(struct kunit *test)
{
 struct cros_ec_proto_test_priv *priv = test->priv;
 struct cros_ec_device *ec_dev = &priv->ec_dev;
 struct ec_xfer_mock *mock;
 int ret;

 /* For cros_ec_get_proto_info() without passthru. */
 {
  mock = cros_kunit_ec_xfer_mock_addx(test, 0, EC_RES_INVALID_COMMAND, 0);
  KUNIT_ASSERT_PTR_NE(test, mock, NULL);
 }

 /* For cros_ec_get_proto_info_legacy(). */
 {
  struct ec_response_hello *data;

  mock = cros_kunit_ec_xfer_mock_add(test, sizeof(*data));
  KUNIT_ASSERT_PTR_NE(test, mock, NULL);

  data = (struct ec_response_hello *)mock->o_data;
  data->out_data = 0xbeefbfbf;
 }

 cros_ec_proto_test_query_all_pretest(test);
 ret = cros_ec_query_all(ec_dev);
 KUNIT_EXPECT_EQ(test, ret, -EBADMSG);
 KUNIT_EXPECT_EQ(test, ec_dev->proto_version, EC_PROTO_VERSION_UNKNOWN);

 /* For cros_ec_get_proto_info() without passthru. */
 {
  mock = cros_kunit_ec_xfer_mock_next();
  KUNIT_EXPECT_PTR_NE(test, mock, NULL);

  KUNIT_EXPECT_EQ(test, mock->msg.version, 0);
  KUNIT_EXPECT_EQ(test, mock->msg.command, EC_CMD_GET_PROTOCOL_INFO);
  KUNIT_EXPECT_EQ(test, mock->msg.insize,
    sizeof(struct ec_response_get_protocol_info));
  KUNIT_EXPECT_EQ(test, mock->msg.outsize, 0);
 }

 /* For cros_ec_get_proto_info_legacy(). */
 {
  mock = cros_kunit_ec_xfer_mock_next();
  KUNIT_EXPECT_PTR_NE(test, mock, NULL);

  KUNIT_EXPECT_EQ(test, mock->msg.version, 0);
  KUNIT_EXPECT_EQ(test, mock->msg.command, EC_CMD_HELLO);
  KUNIT_EXPECT_EQ(test, mock->msg.insize, sizeof(struct ec_response_hello));
  KUNIT_EXPECT_EQ(test, mock->msg.outsize, sizeof(struct ec_params_hello));
 }
}

static void cros_ec_proto_test_query_all_legacy_return0(struct kunit *test)
{
 struct cros_ec_proto_test_priv *priv = test->priv;
 struct cros_ec_device *ec_dev = &priv->ec_dev;
 struct ec_xfer_mock *mock;
 int ret;

 /* For cros_ec_get_proto_info() without passthru. */
 {
  mock = cros_kunit_ec_xfer_mock_addx(test, 0, EC_RES_INVALID_COMMAND, 0);
  KUNIT_ASSERT_PTR_NE(test, mock, NULL);
 }

 /* For cros_ec_get_proto_info_legacy(). */
 {
  mock = cros_kunit_ec_xfer_mock_add(test, 0);
  KUNIT_ASSERT_PTR_NE(test, mock, NULL);
 }

 cros_ec_proto_test_query_all_pretest(test);
 ret = cros_ec_query_all(ec_dev);
 KUNIT_EXPECT_EQ(test, ret, -EPROTO);
 KUNIT_EXPECT_EQ(test, ec_dev->proto_version, EC_PROTO_VERSION_UNKNOWN);

 /* For cros_ec_get_proto_info() without passthru. */
 {
  mock = cros_kunit_ec_xfer_mock_next();
  KUNIT_EXPECT_PTR_NE(test, mock, NULL);

  KUNIT_EXPECT_EQ(test, mock->msg.version, 0);
  KUNIT_EXPECT_EQ(test, mock->msg.command, EC_CMD_GET_PROTOCOL_INFO);
  KUNIT_EXPECT_EQ(test, mock->msg.insize,
    sizeof(struct ec_response_get_protocol_info));
  KUNIT_EXPECT_EQ(test, mock->msg.outsize, 0);
 }

 /* For cros_ec_get_proto_info_legacy(). */
 {
  mock = cros_kunit_ec_xfer_mock_next();
  KUNIT_EXPECT_PTR_NE(test, mock, NULL);

  KUNIT_EXPECT_EQ(test, mock->msg.version, 0);
  KUNIT_EXPECT_EQ(test, mock->msg.command, EC_CMD_HELLO);
  KUNIT_EXPECT_EQ(test, mock->msg.insize, sizeof(struct ec_response_hello));
  KUNIT_EXPECT_EQ(test, mock->msg.outsize, sizeof(struct ec_params_hello));
 }
}

static void cros_ec_proto_test_query_all_no_mkbp(struct kunit *test)
{
 struct cros_ec_proto_test_priv *priv = test->priv;
 struct cros_ec_device *ec_dev = &priv->ec_dev;
 struct ec_xfer_mock *mock;
 int ret;

 /* Set some garbage bytes. */
 ec_dev->mkbp_event_supported = 0xbf;

 /* For cros_ec_get_proto_info() without passthru. */
 {
  struct ec_response_get_protocol_info *data;

  mock = cros_kunit_ec_xfer_mock_add(test, sizeof(*data));
  KUNIT_ASSERT_PTR_NE(test, mock, NULL);

  /*
 * Although it doesn't check the value, provides valid sizes so that
 * cros_ec_query_all() allocates din and dout correctly.
 */

  data = (struct ec_response_get_protocol_info *)mock->o_data;
  data->max_request_packet_size = 0xbe;
  data->max_response_packet_size = 0xef;
 }

 /* For cros_ec_get_proto_info() with passthru. */
 {
  mock = cros_kunit_ec_xfer_mock_addx(test, 0, EC_RES_INVALID_COMMAND, 0);
  KUNIT_ASSERT_PTR_NE(test, mock, NULL);
 }

 /* For cros_ec_get_host_command_version_mask() for MKBP. */
 {
  struct ec_response_get_cmd_versions *data;

  mock = cros_kunit_ec_xfer_mock_add(test, sizeof(*data));
  KUNIT_ASSERT_PTR_NE(test, mock, NULL);

  data = (struct ec_response_get_cmd_versions *)mock->o_data;
  data->version_mask = 0;
 }

 cros_ec_proto_test_query_all_pretest(test);
 ret = cros_ec_query_all(ec_dev);
 KUNIT_EXPECT_EQ(test, ret, 0);

 /* For cros_ec_get_proto_info() without passthru. */
 {
  mock = cros_kunit_ec_xfer_mock_next();
  KUNIT_EXPECT_PTR_NE(test, mock, NULL);

  KUNIT_EXPECT_EQ(test, mock->msg.version, 0);
  KUNIT_EXPECT_EQ(test, mock->msg.command, EC_CMD_GET_PROTOCOL_INFO);
  KUNIT_EXPECT_EQ(test, mock->msg.insize,
    sizeof(struct ec_response_get_protocol_info));
  KUNIT_EXPECT_EQ(test, mock->msg.outsize, 0);
 }

 /* For cros_ec_get_proto_info() with passthru. */
 {
  mock = cros_kunit_ec_xfer_mock_next();
  KUNIT_EXPECT_PTR_NE(test, mock, NULL);

  KUNIT_EXPECT_EQ(test, mock->msg.version, 0);
  KUNIT_EXPECT_EQ(test, mock->msg.command,
    EC_CMD_PASSTHRU_OFFSET(CROS_EC_DEV_PD_INDEX) |
    EC_CMD_GET_PROTOCOL_INFO);
  KUNIT_EXPECT_EQ(test, mock->msg.insize,
    sizeof(struct ec_response_get_protocol_info));
  KUNIT_EXPECT_EQ(test, mock->msg.outsize, 0);
 }

 /* For cros_ec_get_host_command_version_mask() for MKBP. */
 {
  struct ec_params_get_cmd_versions *data;

  mock = cros_kunit_ec_xfer_mock_next();
  KUNIT_EXPECT_PTR_NE(test, mock, NULL);

  KUNIT_EXPECT_EQ(test, mock->msg.version, 0);
  KUNIT_EXPECT_EQ(test, mock->msg.command, EC_CMD_GET_CMD_VERSIONS);
  KUNIT_EXPECT_EQ(test, mock->msg.insize,
    sizeof(struct ec_response_get_cmd_versions));
  KUNIT_EXPECT_EQ(test, mock->msg.outsize, sizeof(*data));

  data = (struct ec_params_get_cmd_versions *)mock->i_data;
  KUNIT_EXPECT_EQ(test, data->cmd, EC_CMD_GET_NEXT_EVENT);

  KUNIT_EXPECT_EQ(test, ec_dev->mkbp_event_supported, 0);
 }
}

static void cros_ec_proto_test_query_all_no_mkbp_return_error(struct kunit *test)
{
 struct cros_ec_proto_test_priv *priv = test->priv;
 struct cros_ec_device *ec_dev = &priv->ec_dev;
 struct ec_xfer_mock *mock;
 int ret;

 /* Set some garbage bytes. */
 ec_dev->mkbp_event_supported = 0xbf;

 /* For cros_ec_get_proto_info() without passthru. */
 {
  struct ec_response_get_protocol_info *data;

  mock = cros_kunit_ec_xfer_mock_add(test, sizeof(*data));
  KUNIT_ASSERT_PTR_NE(test, mock, NULL);

  /*
 * Although it doesn't check the value, provides valid sizes so that
 * cros_ec_query_all() allocates din and dout correctly.
 */

  data = (struct ec_response_get_protocol_info *)mock->o_data;
  data->max_request_packet_size = 0xbe;
  data->max_response_packet_size = 0xef;
 }

 /* For cros_ec_get_proto_info() with passthru. */
 {
  mock = cros_kunit_ec_xfer_mock_addx(test, 0, EC_RES_INVALID_COMMAND, 0);
  KUNIT_ASSERT_PTR_NE(test, mock, NULL);
 }

 /* For cros_ec_get_host_command_version_mask() for MKBP. */
 {
  mock = cros_kunit_ec_xfer_mock_addx(test, 0, EC_RES_INVALID_COMMAND, 0);
  KUNIT_ASSERT_PTR_NE(test, mock, NULL);
 }

 cros_ec_proto_test_query_all_pretest(test);
 ret = cros_ec_query_all(ec_dev);
 KUNIT_EXPECT_EQ(test, ret, 0);

 /* For cros_ec_get_proto_info() without passthru. */
 {
  mock = cros_kunit_ec_xfer_mock_next();
  KUNIT_EXPECT_PTR_NE(test, mock, NULL);

  KUNIT_EXPECT_EQ(test, mock->msg.version, 0);
  KUNIT_EXPECT_EQ(test, mock->msg.command, EC_CMD_GET_PROTOCOL_INFO);
  KUNIT_EXPECT_EQ(test, mock->msg.insize,
    sizeof(struct ec_response_get_protocol_info));
  KUNIT_EXPECT_EQ(test, mock->msg.outsize, 0);
 }

 /* For cros_ec_get_proto_info() with passthru. */
 {
  mock = cros_kunit_ec_xfer_mock_next();
  KUNIT_EXPECT_PTR_NE(test, mock, NULL);

  KUNIT_EXPECT_EQ(test, mock->msg.version, 0);
  KUNIT_EXPECT_EQ(test, mock->msg.command,
    EC_CMD_PASSTHRU_OFFSET(CROS_EC_DEV_PD_INDEX) |
    EC_CMD_GET_PROTOCOL_INFO);
  KUNIT_EXPECT_EQ(test, mock->msg.insize,
    sizeof(struct ec_response_get_protocol_info));
  KUNIT_EXPECT_EQ(test, mock->msg.outsize, 0);
 }

 /* For cros_ec_get_host_command_version_mask() for MKBP. */
 {
  struct ec_params_get_cmd_versions *data;

  mock = cros_kunit_ec_xfer_mock_next();
  KUNIT_EXPECT_PTR_NE(test, mock, NULL);

  KUNIT_EXPECT_EQ(test, mock->msg.version, 0);
  KUNIT_EXPECT_EQ(test, mock->msg.command, EC_CMD_GET_CMD_VERSIONS);
  KUNIT_EXPECT_EQ(test, mock->msg.insize,
    sizeof(struct ec_response_get_cmd_versions));
  KUNIT_EXPECT_EQ(test, mock->msg.outsize, sizeof(*data));

  data = (struct ec_params_get_cmd_versions *)mock->i_data;
  KUNIT_EXPECT_EQ(test, data->cmd, EC_CMD_GET_NEXT_EVENT);

  KUNIT_EXPECT_EQ(test, ec_dev->mkbp_event_supported, 0);
 }
}

static void cros_ec_proto_test_query_all_no_mkbp_return0(struct kunit *test)
{
 struct cros_ec_proto_test_priv *priv = test->priv;
 struct cros_ec_device *ec_dev = &priv->ec_dev;
 struct ec_xfer_mock *mock;
 int ret;

 /* Set some garbage bytes. */
 ec_dev->mkbp_event_supported = 0xbf;

 /* For cros_ec_get_proto_info() without passthru. */
 {
  struct ec_response_get_protocol_info *data;

  mock = cros_kunit_ec_xfer_mock_add(test, sizeof(*data));
  KUNIT_ASSERT_PTR_NE(test, mock, NULL);

  /*
 * Although it doesn't check the value, provides valid sizes so that
 * cros_ec_query_all() allocates din and dout correctly.
 */

  data = (struct ec_response_get_protocol_info *)mock->o_data;
  data->max_request_packet_size = 0xbe;
  data->max_response_packet_size = 0xef;
 }

 /* For cros_ec_get_proto_info() with passthru. */
 {
  mock = cros_kunit_ec_xfer_mock_addx(test, 0, EC_RES_INVALID_COMMAND, 0);
  KUNIT_ASSERT_PTR_NE(test, mock, NULL);
 }

 /* For cros_ec_get_host_command_version_mask() for MKBP. */
 {
  mock = cros_kunit_ec_xfer_mock_add(test, 0);
  KUNIT_ASSERT_PTR_NE(test, mock, NULL);
 }

 cros_ec_proto_test_query_all_pretest(test);
 ret = cros_ec_query_all(ec_dev);
 KUNIT_EXPECT_EQ(test, ret, 0);

 /* For cros_ec_get_proto_info() without passthru. */
 {
  mock = cros_kunit_ec_xfer_mock_next();
  KUNIT_EXPECT_PTR_NE(test, mock, NULL);

  KUNIT_EXPECT_EQ(test, mock->msg.version, 0);
  KUNIT_EXPECT_EQ(test, mock->msg.command, EC_CMD_GET_PROTOCOL_INFO);
  KUNIT_EXPECT_EQ(test, mock->msg.insize,
    sizeof(struct ec_response_get_protocol_info));
  KUNIT_EXPECT_EQ(test, mock->msg.outsize, 0);
 }

 /* For cros_ec_get_proto_info() with passthru. */
 {
  mock = cros_kunit_ec_xfer_mock_next();
  KUNIT_EXPECT_PTR_NE(test, mock, NULL);

  KUNIT_EXPECT_EQ(test, mock->msg.version, 0);
  KUNIT_EXPECT_EQ(test, mock->msg.command,
    EC_CMD_PASSTHRU_OFFSET(CROS_EC_DEV_PD_INDEX) |
    EC_CMD_GET_PROTOCOL_INFO);
  KUNIT_EXPECT_EQ(test, mock->msg.insize,
    sizeof(struct ec_response_get_protocol_info));
  KUNIT_EXPECT_EQ(test, mock->msg.outsize, 0);
 }

 /* For cros_ec_get_host_command_version_mask() for MKBP. */
 {
  struct ec_params_get_cmd_versions *data;

  mock = cros_kunit_ec_xfer_mock_next();
  KUNIT_EXPECT_PTR_NE(test, mock, NULL);

  KUNIT_EXPECT_EQ(test, mock->msg.version, 0);
  KUNIT_EXPECT_EQ(test, mock->msg.command, EC_CMD_GET_CMD_VERSIONS);
  KUNIT_EXPECT_EQ(test, mock->msg.insize,
    sizeof(struct ec_response_get_cmd_versions));
  KUNIT_EXPECT_EQ(test, mock->msg.outsize, sizeof(*data));

  data = (struct ec_params_get_cmd_versions *)mock->i_data;
  KUNIT_EXPECT_EQ(test, data->cmd, EC_CMD_GET_NEXT_EVENT);

  KUNIT_EXPECT_EQ(test, ec_dev->mkbp_event_supported, 0);
 }
}

static void cros_ec_proto_test_query_all_no_host_sleep(struct kunit *test)
{
 struct cros_ec_proto_test_priv *priv = test->priv;
 struct cros_ec_device *ec_dev = &priv->ec_dev;
 struct ec_xfer_mock *mock;
 int ret;

 /* Set some garbage bytes. */
 ec_dev->host_sleep_v1 = true;

 /* For cros_ec_get_proto_info() without passthru. */
 {
  struct ec_response_get_protocol_info *data;

  mock = cros_kunit_ec_xfer_mock_add(test, sizeof(*data));
  KUNIT_ASSERT_PTR_NE(test, mock, NULL);

  /*
 * Although it doesn't check the value, provides valid sizes so that
 * cros_ec_query_all() allocates din and dout correctly.
 */

  data = (struct ec_response_get_protocol_info *)mock->o_data;
  data->max_request_packet_size = 0xbe;
  data->max_response_packet_size = 0xef;
 }

 /* For cros_ec_get_proto_info() with passthru. */
 {
  mock = cros_kunit_ec_xfer_mock_addx(test, 0, EC_RES_INVALID_COMMAND, 0);
  KUNIT_ASSERT_PTR_NE(test, mock, NULL);
 }

 /* For cros_ec_get_host_command_version_mask() for MKBP. */
 {
  mock = cros_kunit_ec_xfer_mock_add(test, 0);
  KUNIT_ASSERT_PTR_NE(test, mock, NULL);
 }

 /* For cros_ec_get_host_command_version_mask() for host sleep v1. */
 {
  struct ec_response_get_cmd_versions *data;

  mock = cros_kunit_ec_xfer_mock_add(test, sizeof(*data));
  KUNIT_ASSERT_PTR_NE(test, mock, NULL);

  data = (struct ec_response_get_cmd_versions *)mock->o_data;
  data->version_mask = 0;
 }

 cros_ec_proto_test_query_all_pretest(test);
 ret = cros_ec_query_all(ec_dev);
 KUNIT_EXPECT_EQ(test, ret, 0);

 /* For cros_ec_get_proto_info() without passthru. */
 {
  mock = cros_kunit_ec_xfer_mock_next();
  KUNIT_EXPECT_PTR_NE(test, mock, NULL);

  KUNIT_EXPECT_EQ(test, mock->msg.version, 0);
  KUNIT_EXPECT_EQ(test, mock->msg.command, EC_CMD_GET_PROTOCOL_INFO);
  KUNIT_EXPECT_EQ(test, mock->msg.insize,
    sizeof(struct ec_response_get_protocol_info));
  KUNIT_EXPECT_EQ(test, mock->msg.outsize, 0);
 }

 /* For cros_ec_get_proto_info() with passthru. */
 {
  mock = cros_kunit_ec_xfer_mock_next();
  KUNIT_EXPECT_PTR_NE(test, mock, NULL);

  KUNIT_EXPECT_EQ(test, mock->msg.version, 0);
  KUNIT_EXPECT_EQ(test, mock->msg.command,
    EC_CMD_PASSTHRU_OFFSET(CROS_EC_DEV_PD_INDEX) |
    EC_CMD_GET_PROTOCOL_INFO);
  KUNIT_EXPECT_EQ(test, mock->msg.insize,
    sizeof(struct ec_response_get_protocol_info));
  KUNIT_EXPECT_EQ(test, mock->msg.outsize, 0);
 }

 /* For cros_ec_get_host_command_version_mask() for MKBP. */
 {
  mock = cros_kunit_ec_xfer_mock_next();
  KUNIT_EXPECT_PTR_NE(test, mock, NULL);

  KUNIT_EXPECT_EQ(test, mock->msg.version, 0);
  KUNIT_EXPECT_EQ(test, mock->msg.command, EC_CMD_GET_CMD_VERSIONS);
  KUNIT_EXPECT_EQ(test, mock->msg.insize,
    sizeof(struct ec_response_get_cmd_versions));
  KUNIT_EXPECT_EQ(test, mock->msg.outsize, sizeof(struct ec_params_get_cmd_versions));
 }

 /* For cros_ec_get_host_command_version_mask() for host sleep v1. */
 {
  mock = cros_kunit_ec_xfer_mock_next();
  KUNIT_EXPECT_PTR_NE(test, mock, NULL);

  KUNIT_EXPECT_EQ(test, mock->msg.version, 0);
  KUNIT_EXPECT_EQ(test, mock->msg.command, EC_CMD_GET_CMD_VERSIONS);
  KUNIT_EXPECT_EQ(test, mock->msg.insize,
    sizeof(struct ec_response_get_cmd_versions));
  KUNIT_EXPECT_EQ(test, mock->msg.outsize, sizeof(struct ec_params_get_cmd_versions));

  KUNIT_EXPECT_FALSE(test, ec_dev->host_sleep_v1);
 }
}

static void cros_ec_proto_test_query_all_no_host_sleep_return0(struct kunit *test)
{
 struct cros_ec_proto_test_priv *priv = test->priv;
 struct cros_ec_device *ec_dev = &priv->ec_dev;
 struct ec_xfer_mock *mock;
 int ret;

 /* Set some garbage bytes. */
 ec_dev->host_sleep_v1 = true;

 /* For cros_ec_get_proto_info() without passthru. */
 {
  struct ec_response_get_protocol_info *data;

  mock = cros_kunit_ec_xfer_mock_add(test, sizeof(*data));
  KUNIT_ASSERT_PTR_NE(test, mock, NULL);

  /*
 * Although it doesn't check the value, provides valid sizes so that
 * cros_ec_query_all() allocates din and dout correctly.
 */

  data = (struct ec_response_get_protocol_info *)mock->o_data;
  data->max_request_packet_size = 0xbe;
  data->max_response_packet_size = 0xef;
 }

 /* For cros_ec_get_proto_info() with passthru. */
 {
  mock = cros_kunit_ec_xfer_mock_addx(test, 0, EC_RES_INVALID_COMMAND, 0);
  KUNIT_ASSERT_PTR_NE(test, mock, NULL);
 }

 /* For cros_ec_get_host_command_version_mask() for MKBP. */
 {
  struct ec_response_get_cmd_versions *data;

  mock = cros_kunit_ec_xfer_mock_add(test, sizeof(*data));
  KUNIT_ASSERT_PTR_NE(test, mock, NULL);

  /* In order to pollute next cros_ec_get_host_command_version_mask(). */
  data = (struct ec_response_get_cmd_versions *)mock->o_data;
  data->version_mask = 0xbeef;
 }

 /* For cros_ec_get_host_command_version_mask() for host sleep v1. */
 {
  mock = cros_kunit_ec_xfer_mock_add(test, 0);
  KUNIT_ASSERT_PTR_NE(test, mock, NULL);
 }

 cros_ec_proto_test_query_all_pretest(test);
 ret = cros_ec_query_all(ec_dev);
 KUNIT_EXPECT_EQ(test, ret, 0);

 /* For cros_ec_get_proto_info() without passthru. */
 {
  mock = cros_kunit_ec_xfer_mock_next();
  KUNIT_EXPECT_PTR_NE(test, mock, NULL);

  KUNIT_EXPECT_EQ(test, mock->msg.version, 0);
  KUNIT_EXPECT_EQ(test, mock->msg.command, EC_CMD_GET_PROTOCOL_INFO);
  KUNIT_EXPECT_EQ(test, mock->msg.insize,
    sizeof(struct ec_response_get_protocol_info));
  KUNIT_EXPECT_EQ(test, mock->msg.outsize, 0);
 }

 /* For cros_ec_get_proto_info() with passthru. */
 {
  mock = cros_kunit_ec_xfer_mock_next();
  KUNIT_EXPECT_PTR_NE(test, mock, NULL);

  KUNIT_EXPECT_EQ(test, mock->msg.version, 0);
  KUNIT_EXPECT_EQ(test, mock->msg.command,
    EC_CMD_PASSTHRU_OFFSET(CROS_EC_DEV_PD_INDEX) |
    EC_CMD_GET_PROTOCOL_INFO);
  KUNIT_EXPECT_EQ(test, mock->msg.insize,
    sizeof(struct ec_response_get_protocol_info));
  KUNIT_EXPECT_EQ(test, mock->msg.outsize, 0);
 }

 /* For cros_ec_get_host_command_version_mask() for MKBP. */
 {
  mock = cros_kunit_ec_xfer_mock_next();
  KUNIT_EXPECT_PTR_NE(test, mock, NULL);

  KUNIT_EXPECT_EQ(test, mock->msg.version, 0);
  KUNIT_EXPECT_EQ(test, mock->msg.command, EC_CMD_GET_CMD_VERSIONS);
  KUNIT_EXPECT_EQ(test, mock->msg.insize,
    sizeof(struct ec_response_get_cmd_versions));
  KUNIT_EXPECT_EQ(test, mock->msg.outsize, sizeof(struct ec_params_get_cmd_versions));
 }

 /* For cros_ec_get_host_command_version_mask() for host sleep v1. */
 {
  mock = cros_kunit_ec_xfer_mock_next();
  KUNIT_EXPECT_PTR_NE(test, mock, NULL);

  KUNIT_EXPECT_EQ(test, mock->msg.version, 0);
  KUNIT_EXPECT_EQ(test, mock->msg.command, EC_CMD_GET_CMD_VERSIONS);
  KUNIT_EXPECT_EQ(test, mock->msg.insize,
    sizeof(struct ec_response_get_cmd_versions));
  KUNIT_EXPECT_EQ(test, mock->msg.outsize, sizeof(struct ec_params_get_cmd_versions));

  KUNIT_EXPECT_FALSE(test, ec_dev->host_sleep_v1);
 }
}

static void cros_ec_proto_test_query_all_default_wake_mask_return_error(struct kunit *test)
{
 struct cros_ec_proto_test_priv *priv = test->priv;
 struct cros_ec_device *ec_dev = &priv->ec_dev;
 struct ec_xfer_mock *mock;
 int ret;

 /* Set some garbage bytes. */
 ec_dev->host_event_wake_mask = U32_MAX;

 /* For cros_ec_get_proto_info() without passthru. */
 {
  struct ec_response_get_protocol_info *data;

  mock = cros_kunit_ec_xfer_mock_add(test, sizeof(*data));
  KUNIT_ASSERT_PTR_NE(test, mock, NULL);

  /*
 * Although it doesn't check the value, provides valid sizes so that
 * cros_ec_query_all() allocates din and dout correctly.
 */

  data = (struct ec_response_get_protocol_info *)mock->o_data;
  data->max_request_packet_size = 0xbe;
  data->max_response_packet_size = 0xef;
 }

 /* For cros_ec_get_proto_info() with passthru. */
 {
  mock = cros_kunit_ec_xfer_mock_addx(test, 0, EC_RES_INVALID_COMMAND, 0);
  KUNIT_ASSERT_PTR_NE(test, mock, NULL);
 }

 /* For cros_ec_get_host_command_version_mask() for MKBP. */
 {
  mock = cros_kunit_ec_xfer_mock_add(test, 0);
  KUNIT_ASSERT_PTR_NE(test, mock, NULL);
 }

 /* For cros_ec_get_host_command_version_mask() for host sleep v1. */
 {
  mock = cros_kunit_ec_xfer_mock_add(test, 0);
  KUNIT_ASSERT_PTR_NE(test, mock, NULL);
 }

 /* For cros_ec_get_host_event_wake_mask(). */
 {
  mock = cros_kunit_ec_xfer_mock_addx(test, 0, EC_RES_INVALID_COMMAND, 0);
  KUNIT_ASSERT_PTR_NE(test, mock, NULL);
 }

 cros_ec_proto_test_query_all_pretest(test);
 ret = cros_ec_query_all(ec_dev);
 KUNIT_EXPECT_EQ(test, ret, 0);

 /* For cros_ec_get_proto_info() without passthru. */
 {
  mock = cros_kunit_ec_xfer_mock_next();
  KUNIT_EXPECT_PTR_NE(test, mock, NULL);

  KUNIT_EXPECT_EQ(test, mock->msg.version, 0);
  KUNIT_EXPECT_EQ(test, mock->msg.command, EC_CMD_GET_PROTOCOL_INFO);
  KUNIT_EXPECT_EQ(test, mock->msg.insize,
    sizeof(struct ec_response_get_protocol_info));
  KUNIT_EXPECT_EQ(test, mock->msg.outsize, 0);
 }

 /* For cros_ec_get_proto_info() with passthru. */
 {
  mock = cros_kunit_ec_xfer_mock_next();
  KUNIT_EXPECT_PTR_NE(test, mock, NULL);

  KUNIT_EXPECT_EQ(test, mock->msg.version, 0);
  KUNIT_EXPECT_EQ(test, mock->msg.command,
    EC_CMD_PASSTHRU_OFFSET(CROS_EC_DEV_PD_INDEX) |
    EC_CMD_GET_PROTOCOL_INFO);
  KUNIT_EXPECT_EQ(test, mock->msg.insize,
    sizeof(struct ec_response_get_protocol_info));
  KUNIT_EXPECT_EQ(test, mock->msg.outsize, 0);
 }

 /* For cros_ec_get_host_command_version_mask() for MKBP. */
 {
  mock = cros_kunit_ec_xfer_mock_next();
  KUNIT_EXPECT_PTR_NE(test, mock, NULL);

  KUNIT_EXPECT_EQ(test, mock->msg.version, 0);
  KUNIT_EXPECT_EQ(test, mock->msg.command, EC_CMD_GET_CMD_VERSIONS);
  KUNIT_EXPECT_EQ(test, mock->msg.insize,
    sizeof(struct ec_response_get_cmd_versions));
  KUNIT_EXPECT_EQ(test, mock->msg.outsize, sizeof(struct ec_params_get_cmd_versions));
 }

 /* For cros_ec_get_host_command_version_mask() for host sleep v1. */
 {
  mock = cros_kunit_ec_xfer_mock_next();
  KUNIT_EXPECT_PTR_NE(test, mock, NULL);

  KUNIT_EXPECT_EQ(test, mock->msg.version, 0);
  KUNIT_EXPECT_EQ(test, mock->msg.command, EC_CMD_GET_CMD_VERSIONS);
  KUNIT_EXPECT_EQ(test, mock->msg.insize,
    sizeof(struct ec_response_get_cmd_versions));
  KUNIT_EXPECT_EQ(test, mock->msg.outsize, sizeof(struct ec_params_get_cmd_versions));
 }

 /* For cros_ec_get_host_event_wake_mask(). */
 {
  u32 mask;

  mock = cros_kunit_ec_xfer_mock_next();
  KUNIT_EXPECT_PTR_NE(test, mock, NULL);

  KUNIT_EXPECT_EQ(test, mock->msg.version, 0);
  KUNIT_EXPECT_EQ(test, mock->msg.command, EC_CMD_HOST_EVENT_GET_WAKE_MASK);
  KUNIT_EXPECT_EQ(test, mock->msg.insize, sizeof(struct ec_response_host_event_mask));
  KUNIT_EXPECT_EQ(test, mock->msg.outsize, 0);

  mask = ec_dev->host_event_wake_mask;
  KUNIT_EXPECT_EQ(test, mask & EC_HOST_EVENT_MASK(EC_HOST_EVENT_LID_CLOSED), 0);
  KUNIT_EXPECT_EQ(test, mask & EC_HOST_EVENT_MASK(EC_HOST_EVENT_AC_DISCONNECTED), 0);
  KUNIT_EXPECT_EQ(test, mask & EC_HOST_EVENT_MASK(EC_HOST_EVENT_BATTERY_LOW), 0);
  KUNIT_EXPECT_EQ(test, mask & EC_HOST_EVENT_MASK(EC_HOST_EVENT_BATTERY_CRITICAL), 0);
  KUNIT_EXPECT_EQ(test, mask & EC_HOST_EVENT_MASK(EC_HOST_EVENT_BATTERY), 0);
  KUNIT_EXPECT_EQ(test, mask & EC_HOST_EVENT_MASK(EC_HOST_EVENT_PD_MCU), 0);
  KUNIT_EXPECT_EQ(test, mask & EC_HOST_EVENT_MASK(EC_HOST_EVENT_BATTERY_STATUS), 0);
 }
}

static void cros_ec_proto_test_query_all_default_wake_mask_return0(struct kunit *test)
{
 struct cros_ec_proto_test_priv *priv = test->priv;
 struct cros_ec_device *ec_dev = &priv->ec_dev;
 struct ec_xfer_mock *mock;
 int ret;

 /* Set some garbage bytes. */
 ec_dev->host_event_wake_mask = U32_MAX;

 /* For cros_ec_get_proto_info() without passthru. */
 {
  struct ec_response_get_protocol_info *data;

  mock = cros_kunit_ec_xfer_mock_add(test, sizeof(*data));
  KUNIT_ASSERT_PTR_NE(test, mock, NULL);

  /*
 * Although it doesn't check the value, provides valid sizes so that
 * cros_ec_query_all() allocates din and dout correctly.
 */

  data = (struct ec_response_get_protocol_info *)mock->o_data;
  data->max_request_packet_size = 0xbe;
  data->max_response_packet_size = 0xef;
 }

 /* For cros_ec_get_proto_info() with passthru. */
 {
  mock = cros_kunit_ec_xfer_mock_addx(test, 0, EC_RES_INVALID_COMMAND, 0);
  KUNIT_ASSERT_PTR_NE(test, mock, NULL);
 }

 /* For cros_ec_get_host_command_version_mask() for MKBP. */
 {
  mock = cros_kunit_ec_xfer_mock_add(test, 0);
  KUNIT_ASSERT_PTR_NE(test, mock, NULL);
 }

 /* For cros_ec_get_host_command_version_mask() for host sleep v1. */
 {
  mock = cros_kunit_ec_xfer_mock_add(test, 0);
  KUNIT_ASSERT_PTR_NE(test, mock, NULL);
 }

 /* For get_host_event_wake_mask(). */
 {
  mock = cros_kunit_ec_xfer_mock_add(test, 0);
  KUNIT_ASSERT_PTR_NE(test, mock, NULL);
 }

 cros_ec_proto_test_query_all_pretest(test);
 ret = cros_ec_query_all(ec_dev);
 KUNIT_EXPECT_EQ(test, ret, 0);

 /* For cros_ec_get_proto_info() without passthru. */
 {
  mock = cros_kunit_ec_xfer_mock_next();
  KUNIT_EXPECT_PTR_NE(test, mock, NULL);

  KUNIT_EXPECT_EQ(test, mock->msg.version, 0);
  KUNIT_EXPECT_EQ(test, mock->msg.command, EC_CMD_GET_PROTOCOL_INFO);
  KUNIT_EXPECT_EQ(test, mock->msg.insize,
    sizeof(struct ec_response_get_protocol_info));
  KUNIT_EXPECT_EQ(test, mock->msg.outsize, 0);
 }

 /* For cros_ec_get_proto_info() with passthru. */
 {
  mock = cros_kunit_ec_xfer_mock_next();
  KUNIT_EXPECT_PTR_NE(test, mock, NULL);

  KUNIT_EXPECT_EQ(test, mock->msg.version, 0);
  KUNIT_EXPECT_EQ(test, mock->msg.command,
    EC_CMD_PASSTHRU_OFFSET(CROS_EC_DEV_PD_INDEX) |
    EC_CMD_GET_PROTOCOL_INFO);
  KUNIT_EXPECT_EQ(test, mock->msg.insize,
    sizeof(struct ec_response_get_protocol_info));
  KUNIT_EXPECT_EQ(test, mock->msg.outsize, 0);
 }

 /* For cros_ec_get_host_command_version_mask() for MKBP. */
 {
  mock = cros_kunit_ec_xfer_mock_next();
  KUNIT_EXPECT_PTR_NE(test, mock, NULL);

  KUNIT_EXPECT_EQ(test, mock->msg.version, 0);
  KUNIT_EXPECT_EQ(test, mock->msg.command, EC_CMD_GET_CMD_VERSIONS);
  KUNIT_EXPECT_EQ(test, mock->msg.insize,
    sizeof(struct ec_response_get_cmd_versions));
  KUNIT_EXPECT_EQ(test, mock->msg.outsize, sizeof(struct ec_params_get_cmd_versions));
 }

 /* For cros_ec_get_host_command_version_mask() for host sleep v1. */
 {
  mock = cros_kunit_ec_xfer_mock_next();
  KUNIT_EXPECT_PTR_NE(test, mock, NULL);

  KUNIT_EXPECT_EQ(test, mock->msg.version, 0);
  KUNIT_EXPECT_EQ(test, mock->msg.command, EC_CMD_GET_CMD_VERSIONS);
  KUNIT_EXPECT_EQ(test, mock->msg.insize,
    sizeof(struct ec_response_get_cmd_versions));
  KUNIT_EXPECT_EQ(test, mock->msg.outsize, sizeof(struct ec_params_get_cmd_versions));
 }

 /* For get_host_event_wake_mask(). */
 {
  u32 mask;

  mock = cros_kunit_ec_xfer_mock_next();
  KUNIT_EXPECT_PTR_NE(test, mock, NULL);

  KUNIT_EXPECT_EQ(test, mock->msg.version, 0);
  KUNIT_EXPECT_EQ(test, mock->msg.command, EC_CMD_HOST_EVENT_GET_WAKE_MASK);
  KUNIT_EXPECT_EQ(test, mock->msg.insize, sizeof(struct ec_response_host_event_mask));
  KUNIT_EXPECT_EQ(test, mock->msg.outsize, 0);

  mask = ec_dev->host_event_wake_mask;
  KUNIT_EXPECT_EQ(test, mask & EC_HOST_EVENT_MASK(EC_HOST_EVENT_LID_CLOSED), 0);
  KUNIT_EXPECT_EQ(test, mask & EC_HOST_EVENT_MASK(EC_HOST_EVENT_AC_DISCONNECTED), 0);
  KUNIT_EXPECT_EQ(test, mask & EC_HOST_EVENT_MASK(EC_HOST_EVENT_BATTERY_LOW), 0);
  KUNIT_EXPECT_EQ(test, mask & EC_HOST_EVENT_MASK(EC_HOST_EVENT_BATTERY_CRITICAL), 0);
  KUNIT_EXPECT_EQ(test, mask & EC_HOST_EVENT_MASK(EC_HOST_EVENT_BATTERY), 0);
  KUNIT_EXPECT_EQ(test, mask & EC_HOST_EVENT_MASK(EC_HOST_EVENT_PD_MCU), 0);
  KUNIT_EXPECT_EQ(test, mask & EC_HOST_EVENT_MASK(EC_HOST_EVENT_BATTERY_STATUS), 0);
 }
}

static void cros_ec_proto_test_cmd_xfer_normal(struct kunit *test)
{
 struct cros_ec_proto_test_priv *priv = test->priv;
 struct cros_ec_device *ec_dev = &priv->ec_dev;
 struct ec_xfer_mock *mock;
 int ret;
 DEFINE_RAW_FLEX(struct cros_ec_command, buf, data, 0x100);

 ec_dev->max_request = 0xff;
 ec_dev->max_response = 0xee;
 ec_dev->max_passthru = 0xdd;

 buf->version = 0;
 buf->command = EC_CMD_HELLO;
 buf->insize = 4;
 buf->outsize = 2;
 buf->data[0] = 0x55;
 buf->data[1] = 0xaa;

 {
  u8 *data;

  mock = cros_kunit_ec_xfer_mock_add(test, 4);
  KUNIT_ASSERT_PTR_NE(test, mock, NULL);

  data = (u8 *)mock->o_data;
  data[0] = 0xaa;
  data[1] = 0x55;
  data[2] = 0xcc;
  data[3] = 0x33;
 }

 ret = cros_ec_cmd_xfer(ec_dev, buf);
 KUNIT_EXPECT_EQ(test, ret, 4);

 {
  u8 *data;

  mock = cros_kunit_ec_xfer_mock_next();
  KUNIT_EXPECT_PTR_NE(test, mock, NULL);

  KUNIT_EXPECT_EQ(test, mock->msg.version, 0);
  KUNIT_EXPECT_EQ(test, mock->msg.command, EC_CMD_HELLO);
  KUNIT_EXPECT_EQ(test, mock->msg.insize, 4);
  KUNIT_EXPECT_EQ(test, mock->msg.outsize, 2);

  data = (u8 *)mock->i_data;
  KUNIT_EXPECT_EQ(test, data[0], 0x55);
  KUNIT_EXPECT_EQ(test, data[1], 0xaa);

  KUNIT_EXPECT_EQ(test, buf->data[0], 0xaa);
  KUNIT_EXPECT_EQ(test, buf->data[1], 0x55);
  KUNIT_EXPECT_EQ(test, buf->data[2], 0xcc);
  KUNIT_EXPECT_EQ(test, buf->data[3], 0x33);
 }
}

static void cros_ec_proto_test_cmd_xfer_excess_msg_insize(struct kunit *test)
{
 struct cros_ec_proto_test_priv *priv = test->priv;
 struct cros_ec_device *ec_dev = &priv->ec_dev;
 struct ec_xfer_mock *mock;
 int ret;
 DEFINE_RAW_FLEX(struct cros_ec_command, buf, data, 0x100);

 ec_dev->max_request = 0xff;
 ec_dev->max_response = 0xee;
 ec_dev->max_passthru = 0xdd;

 buf->version = 0;
 buf->command = EC_CMD_HELLO;
 buf->insize = 0xee + 1;
 buf->outsize = 2;

 {
  mock = cros_kunit_ec_xfer_mock_add(test, 0xcc);
  KUNIT_ASSERT_PTR_NE(test, mock, NULL);
 }

 ret = cros_ec_cmd_xfer(ec_dev, buf);
 KUNIT_EXPECT_EQ(test, ret, 0xcc);

 {
  mock = cros_kunit_ec_xfer_mock_next();
  KUNIT_EXPECT_PTR_NE(test, mock, NULL);

  KUNIT_EXPECT_EQ(test, mock->msg.version, 0);
  KUNIT_EXPECT_EQ(test, mock->msg.command, EC_CMD_HELLO);
  KUNIT_EXPECT_EQ(test, mock->msg.insize, 0xee);
  KUNIT_EXPECT_EQ(test, mock->msg.outsize, 2);
 }
}

static void cros_ec_proto_test_cmd_xfer_excess_msg_outsize_without_passthru(struct kunit *test)
{
 struct cros_ec_proto_test_priv *priv = test->priv;
 struct cros_ec_device *ec_dev = &priv->ec_dev;
 int ret;
 DEFINE_RAW_FLEX(struct cros_ec_command, buf, data, 0x100);

 ec_dev->max_request = 0xff;
 ec_dev->max_response = 0xee;
 ec_dev->max_passthru = 0xdd;

 buf->version = 0;
 buf->command = EC_CMD_HELLO;
 buf->insize = 4;
 buf->outsize = 0xff + 1;

 ret = cros_ec_cmd_xfer(ec_dev, buf);
 KUNIT_EXPECT_EQ(test, ret, -EMSGSIZE);
}

static void cros_ec_proto_test_cmd_xfer_excess_msg_outsize_with_passthru(struct kunit *test)
{
 struct cros_ec_proto_test_priv *priv = test->priv;
 struct cros_ec_device *ec_dev = &priv->ec_dev;
 int ret;
 DEFINE_RAW_FLEX(struct cros_ec_command, buf, data, 0x100);

 ec_dev->max_request = 0xff;
 ec_dev->max_response = 0xee;
 ec_dev->max_passthru = 0xdd;

 buf->version = 0;
 buf->command = EC_CMD_PASSTHRU_OFFSET(CROS_EC_DEV_PD_INDEX) + EC_CMD_HELLO;
 buf->insize = 4;
 buf->outsize = 0xdd + 1;

 ret = cros_ec_cmd_xfer(ec_dev, buf);
 KUNIT_EXPECT_EQ(test, ret, -EMSGSIZE);
}

static void cros_ec_proto_test_cmd_xfer_protocol_v3_normal(struct kunit *test)
{
 struct cros_ec_proto_test_priv *priv = test->priv;
 struct cros_ec_device *ec_dev = &priv->ec_dev;
 int ret;
 struct cros_ec_command msg;

 memset(&msg, 0, sizeof(msg));

 ec_dev->proto_version = 3;
 ec_dev->cmd_xfer = cros_kunit_ec_cmd_xfer_mock;
 ec_dev->pkt_xfer = cros_kunit_ec_pkt_xfer_mock;

 ret = cros_ec_cmd_xfer(ec_dev, &msg);
 KUNIT_EXPECT_EQ(test, ret, 0);

 KUNIT_EXPECT_EQ(test, cros_kunit_ec_cmd_xfer_mock_called, 0);
 KUNIT_EXPECT_EQ(test, cros_kunit_ec_pkt_xfer_mock_called, 1);
}

static void cros_ec_proto_test_cmd_xfer_protocol_v3_no_op(struct kunit *test)
{
 struct cros_ec_proto_test_priv *priv = test->priv;
 struct cros_ec_device *ec_dev = &priv->ec_dev;
 int ret;
 struct cros_ec_command msg;

 memset(&msg, 0, sizeof(msg));

 ec_dev->proto_version = 3;
 ec_dev->cmd_xfer = cros_kunit_ec_cmd_xfer_mock;
 ec_dev->pkt_xfer = NULL;

 ret = cros_ec_cmd_xfer(ec_dev, &msg);
 KUNIT_EXPECT_EQ(test, ret, -EIO);
}

static void cros_ec_proto_test_cmd_xfer_protocol_v2_normal(struct kunit *test)
{
 struct cros_ec_proto_test_priv *priv = test->priv;
 struct cros_ec_device *ec_dev = &priv->ec_dev;
 int ret;
 struct cros_ec_command msg;

 memset(&msg, 0, sizeof(msg));

 ec_dev->proto_version = 2;
 ec_dev->cmd_xfer = cros_kunit_ec_cmd_xfer_mock;
 ec_dev->pkt_xfer = cros_kunit_ec_pkt_xfer_mock;

 ret = cros_ec_cmd_xfer(ec_dev, &msg);
 KUNIT_EXPECT_EQ(test, ret, 0);

 KUNIT_EXPECT_EQ(test, cros_kunit_ec_cmd_xfer_mock_called, 1);
 KUNIT_EXPECT_EQ(test, cros_kunit_ec_pkt_xfer_mock_called, 0);
}

static void cros_ec_proto_test_cmd_xfer_protocol_v2_no_op(struct kunit *test)
{
 struct cros_ec_proto_test_priv *priv = test->priv;
 struct cros_ec_device *ec_dev = &priv->ec_dev;
 int ret;
 struct cros_ec_command msg;

 memset(&msg, 0, sizeof(msg));

 ec_dev->proto_version = 2;
 ec_dev->cmd_xfer = NULL;
 ec_dev->pkt_xfer = cros_kunit_ec_pkt_xfer_mock;

 ret = cros_ec_cmd_xfer(ec_dev, &msg);
 KUNIT_EXPECT_EQ(test, ret, -EIO);
}

static void cros_ec_proto_test_cmd_xfer_in_progress_normal(struct kunit *test)
{
 struct cros_ec_proto_test_priv *priv = test->priv;
 struct cros_ec_device *ec_dev = &priv->ec_dev;
 struct ec_xfer_mock *mock;
 int ret;
 struct cros_ec_command msg;

 memset(&msg, 0, sizeof(msg));

 ec_dev->pkt_xfer = cros_kunit_ec_pkt_xfer_mock;

 /* For the first host command to return EC_RES_IN_PROGRESS. */
 {
  mock = cros_kunit_ec_xfer_mock_addx(test, 0, EC_RES_IN_PROGRESS, 0);
  KUNIT_ASSERT_PTR_NE(test, mock, NULL);
 }

 /* For EC_CMD_GET_COMMS_STATUS. */
 {
  struct ec_response_get_comms_status *data;

  mock = cros_kunit_ec_xfer_mock_add(test, sizeof(*data));
  KUNIT_ASSERT_PTR_NE(test, mock, NULL);

  data = (struct ec_response_get_comms_status *)mock->o_data;
  data->flags = 0;
 }

 ret = cros_ec_cmd_xfer(ec_dev, &msg);
 KUNIT_EXPECT_EQ(test, ret, sizeof(struct ec_response_get_comms_status));

 KUNIT_EXPECT_EQ(test, msg.result, EC_RES_SUCCESS);

 /* For the first host command to return EC_RES_IN_PROGRESS. */
 {
  mock = cros_kunit_ec_xfer_mock_next();
  KUNIT_EXPECT_PTR_NE(test, mock, NULL);
 }

 /* For EC_CMD_GET_COMMS_STATUS. */
 {
  mock = cros_kunit_ec_xfer_mock_next();
  KUNIT_EXPECT_PTR_NE(test, mock, NULL);

  KUNIT_EXPECT_EQ(test, mock->msg.version, 0);
  KUNIT_EXPECT_EQ(test, mock->msg.command, EC_CMD_GET_COMMS_STATUS);
  KUNIT_EXPECT_EQ(test, mock->msg.insize,
    sizeof(struct ec_response_get_comms_status));
  KUNIT_EXPECT_EQ(test, mock->msg.outsize, 0);
 }

 KUNIT_EXPECT_EQ(test, cros_kunit_ec_pkt_xfer_mock_called, 2);
}

static void cros_ec_proto_test_cmd_xfer_in_progress_retries_eagain(struct kunit *test)
{
 struct cros_ec_proto_test_priv *priv = test->priv;
 struct cros_ec_device *ec_dev = &priv->ec_dev;
 struct ec_xfer_mock *mock;
 int ret;
 struct cros_ec_command msg;

 memset(&msg, 0, sizeof(msg));

 ec_dev->pkt_xfer = cros_kunit_ec_pkt_xfer_mock;

 /* For the first host command to return EC_RES_IN_PROGRESS. */
 {
  mock = cros_kunit_ec_xfer_mock_addx(test, 0, EC_RES_IN_PROGRESS, 0);
  KUNIT_ASSERT_PTR_NE(test, mock, NULL);
 }

 /* For EC_CMD_GET_COMMS_STATUS EC_COMMAND_RETRIES times. */
 cros_kunit_ec_xfer_mock_default_ret = -EAGAIN;

 ret = cros_ec_cmd_xfer(ec_dev, &msg);
 KUNIT_EXPECT_EQ(test, ret, -EAGAIN);

 /* For EC_CMD_GET_COMMS_STATUS EC_COMMAND_RETRIES times. */
 KUNIT_EXPECT_EQ(test, cros_kunit_ec_pkt_xfer_mock_called, 51);
}

static void cros_ec_proto_test_cmd_xfer_in_progress_retries_status_processing(struct kunit *test)
{
 struct cros_ec_proto_test_priv *priv = test->priv;
 struct cros_ec_device *ec_dev = &priv->ec_dev;
 struct ec_xfer_mock *mock;
 int ret;
 struct cros_ec_command msg;

 memset(&msg, 0, sizeof(msg));

 ec_dev->pkt_xfer = cros_kunit_ec_pkt_xfer_mock;

 /* For the first host command to return EC_RES_IN_PROGRESS. */
 {
  mock = cros_kunit_ec_xfer_mock_addx(test, 0, EC_RES_IN_PROGRESS, 0);
  KUNIT_ASSERT_PTR_NE(test, mock, NULL);
 }

 /* For EC_CMD_GET_COMMS_STATUS EC_COMMAND_RETRIES times. */
 {
  struct ec_response_get_comms_status *data;
  int i;

  for (i = 0; i < 50; ++i) {
   mock = cros_kunit_ec_xfer_mock_add(test, sizeof(*data));
   KUNIT_ASSERT_PTR_NE(test, mock, NULL);

   data = (struct ec_response_get_comms_status *)mock->o_data;
   data->flags |= EC_COMMS_STATUS_PROCESSING;
  }
 }

 ret = cros_ec_cmd_xfer(ec_dev, &msg);
 KUNIT_EXPECT_EQ(test, ret, -EAGAIN);

 /* For EC_CMD_GET_COMMS_STATUS EC_COMMAND_RETRIES times. */
 KUNIT_EXPECT_EQ(test, cros_kunit_ec_pkt_xfer_mock_called, 51);
}

static void cros_ec_proto_test_cmd_xfer_in_progress_xfer_error(struct kunit *test)
{
 struct cros_ec_proto_test_priv *priv = test->priv;
 struct cros_ec_device *ec_dev = &priv->ec_dev;
 struct ec_xfer_mock *mock;
 int ret;
 struct cros_ec_command msg;

 memset(&msg, 0, sizeof(msg));

 /* For the first host command to return EC_RES_IN_PROGRESS. */
 {
  mock = cros_kunit_ec_xfer_mock_addx(test, 0, EC_RES_IN_PROGRESS, 0);
  KUNIT_ASSERT_PTR_NE(test, mock, NULL);
 }

 /* For EC_CMD_GET_COMMS_STATUS. */
 {
  mock = cros_kunit_ec_xfer_mock_addx(test, -EIO, EC_RES_SUCCESS, 0);
  KUNIT_ASSERT_PTR_NE(test, mock, NULL);
 }

 ret = cros_ec_cmd_xfer(ec_dev, &msg);
 KUNIT_EXPECT_EQ(test, ret, -EIO);
}

static void cros_ec_proto_test_cmd_xfer_in_progress_return_error(struct kunit *test)
{
 struct cros_ec_proto_test_priv *priv = test->priv;
 struct cros_ec_device *ec_dev = &priv->ec_dev;
 struct ec_xfer_mock *mock;
 int ret;
 struct cros_ec_command msg;

 memset(&msg, 0, sizeof(msg));

 ec_dev->pkt_xfer = cros_kunit_ec_pkt_xfer_mock;

 /* For the first host command to return EC_RES_IN_PROGRESS. */
 {
  mock = cros_kunit_ec_xfer_mock_addx(test, 0, EC_RES_IN_PROGRESS, 0);
  KUNIT_ASSERT_PTR_NE(test, mock, NULL);
 }

 /* For EC_CMD_GET_COMMS_STATUS. */
 {
  mock = cros_kunit_ec_xfer_mock_addx(test, 0, EC_RES_INVALID_COMMAND, 0);
  KUNIT_ASSERT_PTR_NE(test, mock, NULL);
 }

 ret = cros_ec_cmd_xfer(ec_dev, &msg);
 KUNIT_EXPECT_EQ(test, ret, 0);

 KUNIT_EXPECT_EQ(test, msg.result, EC_RES_INVALID_COMMAND);

 KUNIT_EXPECT_EQ(test, cros_kunit_ec_pkt_xfer_mock_called, 2);
}

static void cros_ec_proto_test_cmd_xfer_in_progress_return0(struct kunit *test)
{
 struct cros_ec_proto_test_priv *priv = test->priv;
 struct cros_ec_device *ec_dev = &priv->ec_dev;
 struct ec_xfer_mock *mock;
 int ret;
 struct cros_ec_command msg;

 memset(&msg, 0, sizeof(msg));

 ec_dev->pkt_xfer = cros_kunit_ec_pkt_xfer_mock;

 /* For the first host command to return EC_RES_IN_PROGRESS. */
 {
  mock = cros_kunit_ec_xfer_mock_addx(test, 0, EC_RES_IN_PROGRESS, 0);
  KUNIT_ASSERT_PTR_NE(test, mock, NULL);
 }

 /* For EC_CMD_GET_COMMS_STATUS. */
 {
  mock = cros_kunit_ec_xfer_mock_add(test, 0);
  KUNIT_ASSERT_PTR_NE(test, mock, NULL);
 }

 ret = cros_ec_cmd_xfer(ec_dev, &msg);
 KUNIT_EXPECT_EQ(test, ret, -EPROTO);

 KUNIT_EXPECT_EQ(test, cros_kunit_ec_pkt_xfer_mock_called, 2);
}

static void cros_ec_proto_test_cmd_xfer_status_normal(struct kunit *test)
{
 struct cros_ec_proto_test_priv *priv = test->priv;
 struct cros_ec_device *ec_dev = &priv->ec_dev;
 struct ec_xfer_mock *mock;
 int ret;
 struct cros_ec_command msg;

 memset(&msg, 0, sizeof(msg));

 /* For cros_ec_cmd_xfer(). */
 {
  mock = cros_kunit_ec_xfer_mock_add(test, 0);
  KUNIT_ASSERT_PTR_NE(test, mock, NULL);
 }

 ret = cros_ec_cmd_xfer_status(ec_dev, &msg);
 KUNIT_EXPECT_EQ(test, ret, 0);
}

static void cros_ec_proto_test_cmd_xfer_status_xfer_error(struct kunit *test)
{
 struct cros_ec_proto_test_priv *priv = test->priv;
 struct cros_ec_device *ec_dev = &priv->ec_dev;
 struct ec_xfer_mock *mock;
 int ret;
 struct cros_ec_command msg;

 memset(&msg, 0, sizeof(msg));

 /* For cros_ec_cmd_xfer(). */
 {
  mock = cros_kunit_ec_xfer_mock_addx(test, -EPROTO, EC_RES_SUCCESS, 0);
  KUNIT_ASSERT_PTR_NE(test, mock, NULL);
 }

 ret = cros_ec_cmd_xfer_status(ec_dev, &msg);
 KUNIT_EXPECT_EQ(test, ret, -EPROTO);
}

static void cros_ec_proto_test_cmd_xfer_status_return_error(struct kunit *test)
{
 struct cros_ec_proto_test_priv *priv = test->priv;
 struct cros_ec_device *ec_dev = &priv->ec_dev;
 struct ec_xfer_mock *mock;
 int ret, i;
 struct cros_ec_command msg;
 static const int map[] = {
  [EC_RES_SUCCESS] = 0,
  [EC_RES_INVALID_COMMAND] = -EOPNOTSUPP,
  [EC_RES_ERROR] = -EIO,
  [EC_RES_INVALID_PARAM] = -EINVAL,
  [EC_RES_ACCESS_DENIED] = -EACCES,
  [EC_RES_INVALID_RESPONSE] = -EPROTO,
  [EC_RES_INVALID_VERSION] = -ENOPROTOOPT,
  [EC_RES_INVALID_CHECKSUM] = -EBADMSG,
  /*
 * EC_RES_IN_PROGRESS is special because cros_ec_send_command() has extra logic to
 * handle it.  Note that default cros_kunit_ec_xfer_mock_default_ret == 0 thus
 * cros_ec_xfer_command() in cros_ec_wait_until_complete() returns 0.  As a result,
 * it returns -EPROTO without calling cros_ec_map_error().
 */

  [EC_RES_IN_PROGRESS] = -EPROTO,
  [EC_RES_UNAVAILABLE] = -ENODATA,
  [EC_RES_TIMEOUT] = -ETIMEDOUT,
  [EC_RES_OVERFLOW] = -EOVERFLOW,
  [EC_RES_INVALID_HEADER] = -EBADR,
  [EC_RES_REQUEST_TRUNCATED] = -EBADR,
  [EC_RES_RESPONSE_TOO_BIG] = -EFBIG,
  [EC_RES_BUS_ERROR] = -EFAULT,
  [EC_RES_BUSY] = -EBUSY,
  [EC_RES_INVALID_HEADER_VERSION] = -EBADMSG,
  [EC_RES_INVALID_HEADER_CRC] = -EBADMSG,
  [EC_RES_INVALID_DATA_CRC] = -EBADMSG,
  [EC_RES_DUP_UNAVAILABLE] = -ENODATA,
 };

 memset(&msg, 0, sizeof(msg));

 for (i = 0; i < ARRAY_SIZE(map); ++i) {
  mock = cros_kunit_ec_xfer_mock_addx(test, 0, i, 0);
  KUNIT_ASSERT_PTR_NE(test, mock, NULL);

  ret = cros_ec_cmd_xfer_status(ec_dev, &msg);
  KUNIT_EXPECT_EQ(test, ret, map[i]);
 }
}

static void cros_ec_proto_test_get_next_event_no_mkbp_event(struct kunit *test)
{
 struct cros_ec_proto_test_priv *priv = test->priv;
 struct cros_ec_device *ec_dev = &priv->ec_dev;
 struct ec_xfer_mock *mock;
 int ret;
 bool wake_event, more_events;

 ec_dev->max_request = 0xff;
 ec_dev->max_response = 0xee;
 ec_dev->mkbp_event_supported = 0;

 /* Set some garbage bytes. */
 wake_event = false;
 more_events = true;

 /* For get_keyboard_state_event(). */
 {
  union ec_response_get_next_data_v3 *data;

  mock = cros_kunit_ec_xfer_mock_add(test, sizeof(*data));
  KUNIT_ASSERT_PTR_NE(test, mock, NULL);

  data = (union ec_response_get_next_data_v3 *)mock->o_data;
  data->host_event = 0xbeef;
 }

 ret = cros_ec_get_next_event(ec_dev, &wake_event, &more_events);
 KUNIT_EXPECT_EQ(test, ret, sizeof(union ec_response_get_next_data_v3));

 KUNIT_EXPECT_EQ(test, ec_dev->event_data.event_type, EC_MKBP_EVENT_KEY_MATRIX);
 KUNIT_EXPECT_EQ(test, ec_dev->event_data.data.host_event, 0xbeef);

 KUNIT_EXPECT_TRUE(test, wake_event);
 KUNIT_EXPECT_FALSE(test, more_events);

 /* For get_keyboard_state_event(). */
 {
  mock = cros_kunit_ec_xfer_mock_next();
  KUNIT_EXPECT_PTR_NE(test, mock, NULL);

  KUNIT_EXPECT_EQ(test, mock->msg.version, 0);
  KUNIT_EXPECT_EQ(test, mock->msg.command, EC_CMD_MKBP_STATE);
  KUNIT_EXPECT_EQ(test, mock->msg.insize, sizeof(union ec_response_get_next_data_v3));
  KUNIT_EXPECT_EQ(test, mock->msg.outsize, 0);
 }
}

static void cros_ec_proto_test_get_next_event_mkbp_event_ec_suspended(struct kunit *test)
{
 struct cros_ec_proto_test_priv *priv = test->priv;
 struct cros_ec_device *ec_dev = &priv->ec_dev;
 int ret;

 ec_dev->mkbp_event_supported = 1;
 ec_dev->suspended = true;

 ret = cros_ec_get_next_event(ec_dev, NULL, NULL);
 KUNIT_EXPECT_EQ(test, ret, -EHOSTDOWN);
}

static void cros_ec_proto_test_get_next_event_mkbp_event_version0(struct kunit *test)
{
 struct cros_ec_proto_test_priv *priv = test->priv;
 struct cros_ec_device *ec_dev = &priv->ec_dev;
 struct ec_xfer_mock *mock;
 int ret;
 bool wake_event, more_events;

 ec_dev->max_request = 0xff;
 ec_dev->max_response = 0xee;
 ec_dev->mkbp_event_supported = 1;

 /* Set some garbage bytes. */
 wake_event = true;
 more_events = false;

 /* For get_next_event_xfer(). */
 {
  struct ec_response_get_next_event *data;

  mock = cros_kunit_ec_xfer_mock_add(test, sizeof(*data));
  KUNIT_ASSERT_PTR_NE(test, mock, NULL);

  data = (struct ec_response_get_next_event *)mock->o_data;
  data->event_type = EC_MKBP_EVENT_SENSOR_FIFO | EC_MKBP_HAS_MORE_EVENTS;
  data->data.sysrq = 0xbeef;
 }

 ret = cros_ec_get_next_event(ec_dev, &wake_event, &more_events);
 KUNIT_EXPECT_EQ(test, ret, sizeof(struct ec_response_get_next_event));

 KUNIT_EXPECT_EQ(test, ec_dev->event_data.event_type, EC_MKBP_EVENT_SENSOR_FIFO);
--> --------------------

--> maximum size reached

--> --------------------

Messung V0.5
C=96 H=95 G=95

¤ Dauer der Verarbeitung: 0.34 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

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.