summaryrefslogtreecommitdiff
path: root/zephyr/test/drivers/host_cmd
diff options
context:
space:
mode:
Diffstat (limited to 'zephyr/test/drivers/host_cmd')
-rw-r--r--zephyr/test/drivers/host_cmd/CMakeLists.txt17
-rw-r--r--zephyr/test/drivers/host_cmd/src/battery_cut_off.c107
-rw-r--r--zephyr/test/drivers/host_cmd/src/get_panic_info.c98
-rw-r--r--zephyr/test/drivers/host_cmd/src/get_pd_port_caps.c58
-rw-r--r--zephyr/test/drivers/host_cmd/src/host_event_commands.c238
-rw-r--r--zephyr/test/drivers/host_cmd/src/host_event_commands_deprecated.c256
-rw-r--r--zephyr/test/drivers/host_cmd/src/keyboard_mkbp.c81
-rw-r--r--zephyr/test/drivers/host_cmd/src/motion_sense.c868
-rw-r--r--zephyr/test/drivers/host_cmd/src/pd_chip_info.c65
-rw-r--r--zephyr/test/drivers/host_cmd/src/pd_control.c129
-rw-r--r--zephyr/test/drivers/host_cmd/src/pd_log.c135
-rw-r--r--zephyr/test/drivers/host_cmd/src/usb_pd_control.c151
12 files changed, 2203 insertions, 0 deletions
diff --git a/zephyr/test/drivers/host_cmd/CMakeLists.txt b/zephyr/test/drivers/host_cmd/CMakeLists.txt
new file mode 100644
index 0000000000..ddd8e4d54c
--- /dev/null
+++ b/zephyr/test/drivers/host_cmd/CMakeLists.txt
@@ -0,0 +1,17 @@
+# Copyright 2022 The ChromiumOS Authors
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+target_sources(app PRIVATE
+ src/battery_cut_off.c
+ src/get_panic_info.c
+ src/get_pd_port_caps.c
+ src/host_event_commands.c
+ src/host_event_commands_deprecated.c
+ src/keyboard_mkbp.c
+ src/motion_sense.c
+ src/pd_control.c
+ src/pd_chip_info.c
+ src/pd_log.c
+ src/usb_pd_control.c
+)
diff --git a/zephyr/test/drivers/host_cmd/src/battery_cut_off.c b/zephyr/test/drivers/host_cmd/src/battery_cut_off.c
new file mode 100644
index 0000000000..ed9d96481d
--- /dev/null
+++ b/zephyr/test/drivers/host_cmd/src/battery_cut_off.c
@@ -0,0 +1,107 @@
+/* Copyright 2022 The ChromiumOS Authors
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include <zephyr/drivers/emul.h>
+#include <zephyr/ztest.h>
+
+#include "battery.h"
+#include "emul/emul_common_i2c.h"
+#include "emul/emul_smart_battery.h"
+#include "hooks.h"
+#include "host_command.h"
+#include "test/drivers/test_state.h"
+#include "test/drivers/utils.h"
+
+struct host_cmd_battery_cut_off_fixture {
+ const struct emul *emul;
+ struct i2c_common_emul_data *i2c_emul;
+};
+
+static void *host_cmd_battery_cut_off_setup(void)
+{
+ static struct host_cmd_battery_cut_off_fixture fixture = {
+ .emul = EMUL_DT_GET(DT_NODELABEL(battery)),
+ };
+
+ fixture.i2c_emul = emul_smart_battery_get_i2c_common_data(fixture.emul);
+
+ return &fixture;
+}
+
+static void host_cmd_battery_cut_off_before(void *f)
+{
+ ARG_UNUSED(f);
+ test_set_battery_level(75);
+}
+
+static void host_cmd_battery_cut_off_after(void *f)
+{
+ struct host_cmd_battery_cut_off_fixture *fixture = f;
+
+ i2c_common_emul_set_write_fail_reg(fixture->i2c_emul,
+ I2C_COMMON_EMUL_NO_FAIL_REG);
+ set_ac_enabled(true);
+ hook_notify(HOOK_AC_CHANGE);
+ k_msleep(500);
+}
+
+ZTEST_SUITE(host_cmd_battery_cut_off, drivers_predicate_post_main,
+ host_cmd_battery_cut_off_setup, host_cmd_battery_cut_off_before,
+ host_cmd_battery_cut_off_after, NULL);
+
+ZTEST_USER_F(host_cmd_battery_cut_off, test_fail_sb_write)
+{
+ int rv;
+ struct host_cmd_handler_args args =
+ BUILD_HOST_COMMAND_SIMPLE(EC_CMD_BATTERY_CUT_OFF, UINT8_C(0));
+
+ /* Force a failure on the battery i2c write to 0x00 */
+ i2c_common_emul_set_write_fail_reg(fixture->i2c_emul, 0);
+
+ rv = host_command_process(&args);
+ zassert_equal(EC_RES_ERROR, rv, "Expected 0, but got %d", rv);
+}
+
+ZTEST_USER(host_cmd_battery_cut_off, test_cutoff_battery)
+{
+ int rv;
+ struct host_cmd_handler_args args =
+ BUILD_HOST_COMMAND_SIMPLE(EC_CMD_BATTERY_CUT_OFF, UINT8_C(0));
+
+ rv = host_command_process(&args);
+ zassert_equal(EC_RES_SUCCESS, rv, "Expected 0, but got %d", rv);
+ zassert_true(battery_is_cut_off(), NULL);
+}
+
+ZTEST_USER(host_cmd_battery_cut_off, test_cutoff_v1)
+{
+ int rv;
+ struct ec_params_battery_cutoff params = {
+ .flags = 0,
+ };
+ struct host_cmd_handler_args args = BUILD_HOST_COMMAND_PARAMS(
+ EC_CMD_BATTERY_CUT_OFF, UINT8_C(1), params);
+
+ rv = host_command_process(&args);
+ zassert_equal(EC_RES_SUCCESS, rv, "Expected 0, but got %d", rv);
+ zassert_true(battery_is_cut_off(), NULL);
+}
+
+ZTEST_USER(host_cmd_battery_cut_off, test_cutoff_at_shutdown)
+{
+ int rv;
+ struct ec_params_battery_cutoff params = {
+ .flags = EC_BATTERY_CUTOFF_FLAG_AT_SHUTDOWN,
+ };
+ struct host_cmd_handler_args args = BUILD_HOST_COMMAND_PARAMS(
+ EC_CMD_BATTERY_CUT_OFF, UINT8_C(1), params);
+
+ rv = host_command_process(&args);
+ zassert_equal(EC_RES_SUCCESS, rv, "Expected 0, but got %d", rv);
+ zassert_false(battery_is_cut_off(), NULL);
+ hook_notify(HOOK_CHIPSET_SHUTDOWN);
+ zassert_true(WAIT_FOR(battery_is_cut_off(), 1500000, k_msleep(250)),
+ NULL);
+}
diff --git a/zephyr/test/drivers/host_cmd/src/get_panic_info.c b/zephyr/test/drivers/host_cmd/src/get_panic_info.c
new file mode 100644
index 0000000000..04b83d07f9
--- /dev/null
+++ b/zephyr/test/drivers/host_cmd/src/get_panic_info.c
@@ -0,0 +1,98 @@
+/* Copyright 2022 The ChromiumOS Authors
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include <zephyr/ztest.h>
+
+#include "host_command.h"
+#include "panic.h"
+#include "test/drivers/test_state.h"
+
+struct host_cmd_get_panic_info_fixture {
+ struct panic_data saved_pdata;
+};
+
+static void *host_cmd_get_panic_info_setup(void)
+{
+ static struct host_cmd_get_panic_info_fixture fixture = { 0 };
+
+ return &fixture;
+}
+
+static void host_cmd_get_panic_info_before(void *f)
+{
+ struct host_cmd_get_panic_info_fixture *fixture = f;
+ struct panic_data *pdata = get_panic_data_write();
+
+ fixture->saved_pdata = *pdata;
+}
+
+static void host_cmd_get_panic_info_after(void *f)
+{
+ struct host_cmd_get_panic_info_fixture *fixture = f;
+ struct panic_data *pdata = get_panic_data_write();
+
+ *pdata = fixture->saved_pdata;
+}
+
+ZTEST_SUITE(host_cmd_get_panic_info, drivers_predicate_post_main,
+ host_cmd_get_panic_info_setup, host_cmd_get_panic_info_before,
+ host_cmd_get_panic_info_after, NULL);
+
+ZTEST_USER(host_cmd_get_panic_info, test_get_panic_info)
+{
+ struct panic_data *pdata = get_panic_data_write();
+ struct panic_data response = { 0 };
+ struct host_cmd_handler_args args = BUILD_HOST_COMMAND_RESPONSE(
+ EC_CMD_GET_PANIC_INFO, UINT8_C(0), response);
+
+ pdata->arch = 0;
+ pdata->struct_version = 1;
+ pdata->flags = 2;
+ pdata->reserved = 3;
+ pdata->struct_size = sizeof(struct panic_data);
+ pdata->magic = PANIC_DATA_MAGIC;
+
+ zassert_ok(host_command_process(&args), NULL);
+ zassert_equal(sizeof(struct panic_data), args.response_size, NULL);
+ zassert_equal(0, response.arch, NULL);
+ zassert_equal(1, response.struct_version, NULL);
+ zassert_equal(2, response.flags, NULL);
+ zassert_equal(3, response.reserved, NULL);
+ zassert_equal(sizeof(struct panic_data), response.struct_size, NULL);
+ zassert_equal(PANIC_DATA_MAGIC, response.magic, NULL);
+ zassert_equal(pdata->flags & PANIC_DATA_FLAG_OLD_HOSTCMD,
+ PANIC_DATA_FLAG_OLD_HOSTCMD, NULL);
+}
+
+ZTEST_USER(host_cmd_get_panic_info, test_get_panic_info_bad_magic)
+{
+ struct panic_data *pdata = get_panic_data_write();
+ struct panic_data expected = { 0 };
+ struct panic_data response = { 0 };
+ struct host_cmd_handler_args args = BUILD_HOST_COMMAND_RESPONSE(
+ EC_CMD_GET_PANIC_INFO, UINT8_C(0), response);
+
+ pdata->magic = PANIC_DATA_MAGIC + 1;
+ zassert_ok(host_command_process(&args), NULL);
+ /* Check that nothing was written to response */
+ zassert_mem_equal(&response, &expected, sizeof(struct panic_data),
+ NULL);
+}
+
+ZTEST_USER(host_cmd_get_panic_info, test_get_panic_info_size_is_zero)
+{
+ struct panic_data *pdata = get_panic_data_write();
+ struct panic_data expected = { 0 };
+ struct panic_data response = { 0 };
+ struct host_cmd_handler_args args = BUILD_HOST_COMMAND_RESPONSE(
+ EC_CMD_GET_PANIC_INFO, UINT8_C(0), response);
+
+ pdata->magic = PANIC_DATA_MAGIC;
+ pdata->struct_size = 0;
+ zassert_ok(host_command_process(&args), NULL);
+ /* Check that nothing was written to response */
+ zassert_mem_equal(&response, &expected, sizeof(struct panic_data),
+ NULL);
+}
diff --git a/zephyr/test/drivers/host_cmd/src/get_pd_port_caps.c b/zephyr/test/drivers/host_cmd/src/get_pd_port_caps.c
new file mode 100644
index 0000000000..907329f8a1
--- /dev/null
+++ b/zephyr/test/drivers/host_cmd/src/get_pd_port_caps.c
@@ -0,0 +1,58 @@
+/* Copyright 2022 The ChromiumOS Authors
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include <zephyr/shell/shell.h>
+#include <zephyr/ztest.h>
+
+#include "console.h"
+#include "ec_commands.h"
+#include "test/drivers/test_state.h"
+#include "test/drivers/utils.h"
+
+ZTEST_USER(host_cmd_get_pd_port_caps, test_good_index)
+{
+ struct ec_params_get_pd_port_caps params = { .port = 0 };
+ struct ec_response_get_pd_port_caps response;
+ struct host_cmd_handler_args args = BUILD_HOST_COMMAND(
+ EC_CMD_GET_PD_PORT_CAPS, 0, response, params);
+
+ zassert_ok(host_command_process(&args),
+ "Failed to process get_pd_port_caps for port %d",
+ params.port);
+
+ /* Verify standard Chromebook responses for these fields */
+ zassert_equal(response.pd_power_role_cap, EC_PD_POWER_ROLE_DUAL,
+ "Bad dual role");
+ zassert_equal(response.pd_try_power_role_cap,
+ EC_PD_TRY_POWER_ROLE_SOURCE, "Bad try role");
+ zassert_equal(response.pd_data_role_cap, EC_PD_DATA_ROLE_DUAL,
+ "Bad data role");
+ zassert_equal(response.pd_port_location, EC_PD_PORT_LOCATION_UNKNOWN,
+ "Unexpected port location");
+}
+
+ZTEST_USER(host_cmd_get_pd_port_caps, test_bad_index)
+{
+ struct ec_params_get_pd_port_caps params = { .port = 32 };
+ struct ec_response_get_pd_port_caps response;
+ struct host_cmd_handler_args args = BUILD_HOST_COMMAND(
+ EC_CMD_GET_PD_PORT_CAPS, 0, response, params);
+
+ zassert_equal(host_command_process(&args), EC_RES_INVALID_PARAM,
+ "Failed to fail get_pd_port_caps for port %d",
+ params.port);
+}
+
+static void host_cmd_get_pd_port_caps_begin(void *data)
+{
+ ARG_UNUSED(data);
+
+ /* Assume we have at least one USB-C port */
+ zassume_true(board_get_usb_pd_port_count() > 0,
+ "Insufficient TCPCs found");
+}
+
+ZTEST_SUITE(host_cmd_get_pd_port_caps, drivers_predicate_post_main, NULL,
+ host_cmd_get_pd_port_caps_begin, NULL, NULL);
diff --git a/zephyr/test/drivers/host_cmd/src/host_event_commands.c b/zephyr/test/drivers/host_cmd/src/host_event_commands.c
new file mode 100644
index 0000000000..c2f7e72045
--- /dev/null
+++ b/zephyr/test/drivers/host_cmd/src/host_event_commands.c
@@ -0,0 +1,238 @@
+/* Copyright 2022 The ChromiumOS Authors
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include <zephyr/ztest.h>
+#include "include/lpc.h"
+#include "test/drivers/test_state.h"
+#include "test/drivers/utils.h"
+
+struct host_cmd_host_event_commands_fixture {
+ struct host_events_ctx ctx;
+};
+
+static void *host_cmd_host_event_commands_setup(void)
+{
+ static struct host_cmd_host_event_commands_fixture fixture = { 0 };
+
+ return &fixture;
+}
+
+static void host_cmd_host_event_commands_before(void *fixture)
+{
+ struct host_cmd_host_event_commands_fixture *f = fixture;
+
+ host_events_save(&f->ctx);
+}
+
+static void host_cmd_host_event_commands_after(void *fixture)
+{
+ struct host_cmd_host_event_commands_fixture *f = fixture;
+
+ host_events_restore(&f->ctx);
+}
+
+ZTEST_SUITE(host_cmd_host_event_commands, drivers_predicate_post_main,
+ host_cmd_host_event_commands_setup,
+ host_cmd_host_event_commands_before,
+ host_cmd_host_event_commands_after, NULL);
+
+/**
+ * @brief TestPurpose: Verify EC_CMD_HOST_EVENT invalid host command.
+ */
+ZTEST_USER(host_cmd_host_event_commands, test_host_event_invalid_cmd)
+{
+ enum ec_status ret_val;
+ struct ec_response_host_event result = { 0 };
+
+ ret_val = host_cmd_host_event(0xFF, 0, &result);
+
+ zassert_equal(ret_val, EC_RES_INVALID_PARAM, "Expected=%d, returned=%d",
+ EC_RES_INVALID_PARAM, ret_val);
+}
+
+/**
+ * @brief TestPurpose: Verify EC_CMD_HOST_EVENT get host command.
+ */
+ZTEST_USER(host_cmd_host_event_commands, test_host_event_get_cmd)
+{
+ enum ec_status ret_val;
+ struct ec_response_host_event result = { 0 };
+ struct {
+ uint8_t mask;
+ enum ec_status result;
+ } event_get[] = {
+ { EC_HOST_EVENT_MAIN, EC_RES_ACCESS_DENIED },
+ { EC_HOST_EVENT_B, EC_RES_SUCCESS },
+#ifdef CONFIG_HOSTCMD_X86
+ { EC_HOST_EVENT_SCI_MASK, EC_RES_SUCCESS },
+ { EC_HOST_EVENT_SMI_MASK, EC_RES_SUCCESS },
+ { EC_HOST_EVENT_ALWAYS_REPORT_MASK, EC_RES_SUCCESS },
+ { EC_HOST_EVENT_ACTIVE_WAKE_MASK, EC_RES_SUCCESS },
+#ifdef CONFIG_POWER_S0IX
+ { EC_HOST_EVENT_LAZY_WAKE_MASK_S0IX, EC_RES_SUCCESS },
+#endif /* CONFIG_POWER_S0IX */
+ { EC_HOST_EVENT_LAZY_WAKE_MASK_S3, EC_RES_SUCCESS },
+ { EC_HOST_EVENT_LAZY_WAKE_MASK_S5, EC_RES_SUCCESS },
+#endif /* CONFIG_HOSTCMD_X86 */
+ { 0xFF, EC_RES_INVALID_PARAM },
+ };
+
+ for (int i = 0; i < ARRAY_SIZE(event_get); i++) {
+ ret_val = host_cmd_host_event(EC_HOST_EVENT_GET,
+ event_get[i].mask, &result);
+ zassert_equal(ret_val, event_get[i].result,
+ "[%d] Expected=%d, returned=%d", i,
+ event_get[i].result, ret_val);
+ }
+}
+
+/**
+ * @brief TestPurpose: Verify EC_CMD_HOST_EVENT set host command.
+ */
+ZTEST_USER(host_cmd_host_event_commands, test_host_event_set_cmd)
+{
+ enum ec_status ret_val;
+ struct ec_response_host_event result = { 0 };
+ struct {
+ uint8_t mask;
+ enum ec_status result;
+ } event_set[] = {
+ { EC_HOST_EVENT_MAIN, EC_RES_ACCESS_DENIED },
+ { EC_HOST_EVENT_B, EC_RES_ACCESS_DENIED },
+#ifdef CONFIG_HOSTCMD_X86
+ { EC_HOST_EVENT_SCI_MASK, EC_RES_SUCCESS },
+ { EC_HOST_EVENT_SMI_MASK, EC_RES_SUCCESS },
+ { EC_HOST_EVENT_ALWAYS_REPORT_MASK, EC_RES_SUCCESS },
+ { EC_HOST_EVENT_ACTIVE_WAKE_MASK, EC_RES_SUCCESS },
+#ifdef CONFIG_POWER_S0IX
+ { EC_HOST_EVENT_LAZY_WAKE_MASK_S0IX, EC_RES_SUCCESS },
+#endif /* CONFIG_POWER_S0IX */
+ { EC_HOST_EVENT_LAZY_WAKE_MASK_S3, EC_RES_SUCCESS },
+ { EC_HOST_EVENT_LAZY_WAKE_MASK_S5, EC_RES_SUCCESS },
+#endif /* CONFIG_HOSTCMD_X86 */
+ { 0xFF, EC_RES_INVALID_PARAM },
+ };
+
+ for (int i = 0; i < ARRAY_SIZE(event_set); i++) {
+ ret_val = host_cmd_host_event(EC_HOST_EVENT_SET,
+ event_set[i].mask, &result);
+ zassert_equal(ret_val, event_set[i].result,
+ "[%d] Expected=%d, returned=%d", i,
+ event_set[i].result, ret_val);
+ }
+}
+
+/**
+ * @brief TestPurpose: Verify EC_CMD_HOST_EVENT clear host command.
+ */
+ZTEST_USER(host_cmd_host_event_commands, test_host_event_clear_cmd)
+{
+ enum ec_status ret_val;
+ struct ec_response_host_event result = { 0 };
+ struct {
+ uint8_t mask;
+ enum ec_status result;
+ } event_set[] = {
+ { EC_HOST_EVENT_MAIN, EC_RES_SUCCESS },
+ { EC_HOST_EVENT_B, EC_RES_SUCCESS },
+#ifdef CONFIG_HOSTCMD_X86
+ { EC_HOST_EVENT_SCI_MASK, EC_RES_ACCESS_DENIED },
+ { EC_HOST_EVENT_SMI_MASK, EC_RES_ACCESS_DENIED },
+ { EC_HOST_EVENT_ALWAYS_REPORT_MASK, EC_RES_ACCESS_DENIED },
+ { EC_HOST_EVENT_ACTIVE_WAKE_MASK, EC_RES_ACCESS_DENIED },
+#ifdef CONFIG_POWER_S0IX
+ { EC_HOST_EVENT_LAZY_WAKE_MASK_S0IX, EC_RES_ACCESS_DENIED },
+#endif /* CONFIG_POWER_S0IX */
+ { EC_HOST_EVENT_LAZY_WAKE_MASK_S3, EC_RES_ACCESS_DENIED },
+ { EC_HOST_EVENT_LAZY_WAKE_MASK_S5, EC_RES_ACCESS_DENIED },
+#endif /* CONFIG_HOSTCMD_X86 */
+ { 0xFF, EC_RES_INVALID_PARAM },
+ };
+
+ for (int i = 0; i < ARRAY_SIZE(event_set); i++) {
+ ret_val = host_cmd_host_event(EC_HOST_EVENT_CLEAR,
+ event_set[i].mask, &result);
+ zassert_equal(ret_val, event_set[i].result,
+ "Expected [%d] result=%d, returned=%d", i,
+ event_set[i].result, ret_val);
+ }
+}
+
+enum ec_status host_event_mask_cmd_helper(uint32_t command, uint32_t mask,
+ struct ec_response_host_event_mask *r)
+{
+ enum ec_status ret_val;
+
+ struct ec_params_host_event_mask params = {
+ .mask = mask,
+ };
+ struct host_cmd_handler_args args =
+ BUILD_HOST_COMMAND(command, 0, *r, params);
+
+ ret_val = host_command_process(&args);
+
+ return ret_val;
+}
+
+/**
+ * @brief TestPurpose: Verify EC_CMD_HOST_EVENT_CLEAR clear host command.
+ */
+ZTEST_USER(host_cmd_host_event_commands, test_host_event_clear__cmd)
+{
+ enum ec_status ret_val;
+ host_event_t events;
+ host_event_t mask = EC_HOST_EVENT_MASK(EC_HOST_EVENT_KEYBOARD_RECOVERY);
+ host_event_t lpc_event_mask;
+ struct ec_response_host_event_mask response = { 0 };
+
+ lpc_event_mask = lpc_get_host_event_mask(LPC_HOST_EVENT_SMI);
+ lpc_set_host_event_mask(LPC_HOST_EVENT_SMI, lpc_event_mask | mask);
+
+ host_set_single_event(EC_HOST_EVENT_KEYBOARD_RECOVERY);
+ events = host_get_events();
+
+ zassert_true(events & mask, "events=0x%X", events);
+
+ ret_val = host_event_mask_cmd_helper(EC_CMD_HOST_EVENT_CLEAR, mask,
+ &response);
+
+ zassert_equal(ret_val, EC_RES_SUCCESS, "Expected %d, returned %d",
+ EC_RES_SUCCESS, ret_val);
+
+ events = host_get_events();
+ zassert_false(events & mask, "events=0x%X", events);
+}
+
+/**
+ * @brief TestPurpose: Verify EC_CMD_HOST_EVENT_CLEAR_B clear host command.
+ */
+ZTEST_USER(host_cmd_host_event_commands, test_host_event_clear_b_cmd)
+{
+ enum ec_status ret_val;
+ host_event_t events_b;
+ host_event_t mask = EC_HOST_EVENT_MASK(EC_HOST_EVENT_KEYBOARD_RECOVERY);
+ host_event_t lpc_event_mask;
+ struct ec_response_host_event_mask response = { 0 };
+ struct ec_response_host_event result = { 0 };
+
+ lpc_event_mask = lpc_get_host_event_mask(LPC_HOST_EVENT_SMI);
+ lpc_set_host_event_mask(LPC_HOST_EVENT_SMI, lpc_event_mask | mask);
+
+ host_set_single_event(EC_HOST_EVENT_KEYBOARD_RECOVERY);
+
+ host_cmd_host_event(EC_HOST_EVENT_GET, EC_HOST_EVENT_B, &result);
+ events_b = result.value;
+ zassert_true(events_b & mask, "events_b=0x%X", events_b);
+
+ ret_val = host_event_mask_cmd_helper(EC_CMD_HOST_EVENT_CLEAR_B, mask,
+ &response);
+
+ zassert_equal(ret_val, EC_RES_SUCCESS, "Expected %d, returned %d",
+ EC_RES_SUCCESS, ret_val);
+
+ host_cmd_host_event(EC_HOST_EVENT_GET, EC_HOST_EVENT_B, &result);
+ events_b = result.value;
+ zassert_false(events_b & mask, "events_b=0x%X", events_b);
+}
diff --git a/zephyr/test/drivers/host_cmd/src/host_event_commands_deprecated.c b/zephyr/test/drivers/host_cmd/src/host_event_commands_deprecated.c
new file mode 100644
index 0000000000..6d0a386d6e
--- /dev/null
+++ b/zephyr/test/drivers/host_cmd/src/host_event_commands_deprecated.c
@@ -0,0 +1,256 @@
+/* Copyright 2022 The ChromiumOS Authors
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+/* Tests for deprecated EC_CMD_HOST_EVENT_* commands */
+
+#include <zephyr/ztest.h>
+#include "include/lpc.h"
+#include "test/drivers/test_state.h"
+#include "test/drivers/utils.h"
+
+#define HOST_EVENT_TEST_MASK_VAL EC_HOST_EVENT_MASK(EC_HOST_EVENT_LID_OPEN)
+
+static void
+host_event_get_wake_mask_helper(struct ec_response_host_event_mask *r)
+{
+ enum ec_status ret_val;
+ struct host_cmd_handler_args args = BUILD_HOST_COMMAND_RESPONSE(
+ EC_CMD_HOST_EVENT_GET_WAKE_MASK, 0, *r);
+
+ ret_val = host_command_process(&args);
+
+ /* EC_CMD_HOST_EVENT_GET_WAKE_MASK always returns success */
+ zassert_equal(ret_val, EC_RES_SUCCESS, "Expected %d, returned %d",
+ EC_RES_SUCCESS, ret_val);
+}
+
+static void host_event_set_wake_mask_helper(uint32_t mask)
+{
+ enum ec_status ret_val;
+ struct ec_params_host_event_mask params = { .mask = mask };
+ struct host_cmd_handler_args args = BUILD_HOST_COMMAND_PARAMS(
+ EC_CMD_HOST_EVENT_SET_WAKE_MASK, 0, params);
+
+ ret_val = host_command_process(&args);
+
+ /* EC_CMD_HOST_EVENT_SET_WAKE_MASK always returns success */
+ zassert_equal(ret_val, EC_RES_SUCCESS, "Expected %d, returned %d",
+ EC_RES_SUCCESS, ret_val);
+}
+
+/**
+ * @brief TestPurpose: Verify EC_CMD_HOST_EVENT_GET_WAKE_MASK host command.
+ */
+ZTEST_USER(host_cmd_host_event_commands, test_host_event_get_wake_mask)
+{
+#ifdef CONFIG_HOSTCMD_X86
+ struct ec_response_host_event_mask result = { 0 };
+
+ host_event_get_wake_mask_helper(&result);
+#else
+ ztest_test_skip();
+#endif
+}
+
+/**
+ * @brief TestPurpose: Verify EC_CMD_HOST_EVENT_SET_WAKE_MASK host command.
+ */
+ZTEST_USER(host_cmd_host_event_commands, test_host_event_set_wake_mask)
+{
+#ifdef CONFIG_HOSTCMD_X86
+ struct ec_response_host_event_mask result = { 0 };
+
+ /* Read the current mask */
+ host_event_get_wake_mask_helper(&result);
+
+ /* Default mask is expected to be clear */
+ zassert_false(result.mask, "Default host event wake mask is not clear");
+
+ host_event_set_wake_mask_helper(HOST_EVENT_TEST_MASK_VAL);
+
+ /* Verify the mask changed */
+ host_event_get_wake_mask_helper(&result);
+
+ zassert_equal(result.mask, HOST_EVENT_TEST_MASK_VAL,
+ "Expected wake mask 0x%08x, returned mask 0x%08x",
+ HOST_EVENT_TEST_MASK_VAL, result.mask);
+
+ /* Clean up the mask */
+ host_event_set_wake_mask_helper(0);
+#else
+ ztest_test_skip();
+#endif
+}
+
+static void
+host_event_get_smi_mask_helper(struct ec_response_host_event_mask *r)
+{
+ enum ec_status ret_val;
+ struct host_cmd_handler_args args = BUILD_HOST_COMMAND_RESPONSE(
+ EC_CMD_HOST_EVENT_GET_SMI_MASK, 0, *r);
+
+ ret_val = host_command_process(&args);
+
+ /* EC_CMD_HOST_EVENT_GET_SMI_MASK always returns success */
+ zassert_equal(ret_val, EC_RES_SUCCESS, "Expected %d, returned %d",
+ EC_RES_SUCCESS, ret_val);
+}
+
+static void host_event_set_smi_mask_helper(uint32_t mask)
+{
+ enum ec_status ret_val;
+ struct ec_params_host_event_mask params = { .mask = mask };
+ struct host_cmd_handler_args args = BUILD_HOST_COMMAND_PARAMS(
+ EC_CMD_HOST_EVENT_SET_SMI_MASK, 0, params);
+
+ ret_val = host_command_process(&args);
+
+ /* EC_CMD_HOST_EVENT_SET_SMI_MASK always returns success */
+ zassert_equal(ret_val, EC_RES_SUCCESS, "Expected %d, returned %d",
+ EC_RES_SUCCESS, ret_val);
+}
+
+/**
+ * @brief TestPurpose: Verify EC_CMD_HOST_EVENT_GET_SMI_MASK host command.
+ */
+ZTEST_USER(host_cmd_host_event_commands, test_host_event_get_smi_mask)
+{
+#ifdef CONFIG_HOSTCMD_X86
+ struct ec_response_host_event_mask result = { 0 };
+
+ host_event_get_smi_mask_helper(&result);
+#else
+ ztest_test_skip();
+#endif
+}
+
+/**
+ * @brief TestPurpose: Verify EC_CMD_HOST_EVENT_SET_SMI_MASK host command.
+ */
+ZTEST_USER(host_cmd_host_event_commands, test_host_event_set_smi_mask)
+{
+#ifdef CONFIG_HOSTCMD_X86
+ struct ec_response_host_event_mask result = { 0 };
+
+ /* Read the current mask */
+ host_event_get_smi_mask_helper(&result);
+
+ /* Default mask is expected to be clear */
+ zassert_false(result.mask, "Default host event SMI mask is not clear");
+
+ host_event_set_smi_mask_helper(HOST_EVENT_TEST_MASK_VAL);
+
+ /* Verify the mask changed */
+ host_event_get_smi_mask_helper(&result);
+
+ zassert_equal(result.mask, HOST_EVENT_TEST_MASK_VAL,
+ "Expected SMI mask 0x%08x, returned mask 0x%08x",
+ HOST_EVENT_TEST_MASK_VAL, result.mask);
+
+ /* Clean up the mask */
+ host_event_set_smi_mask_helper(0);
+#else
+ ztest_test_skip();
+#endif
+}
+
+static void host_event_get_b_helper(struct ec_response_host_event_mask *r)
+{
+ enum ec_status ret_val;
+ struct host_cmd_handler_args args =
+ BUILD_HOST_COMMAND_RESPONSE(EC_CMD_HOST_EVENT_GET_B, 0, *r);
+
+ ret_val = host_command_process(&args);
+
+ /* EC_CMD_HOST_EVENT_GET_B always returns success */
+ zassert_equal(ret_val, EC_RES_SUCCESS, "Expected %d, returned %d",
+ EC_RES_SUCCESS, ret_val);
+}
+
+/**
+ * @brief TestPurpose: Verify EC_CMD_HOST_EVENT_GET_B host command.
+ */
+ZTEST_USER(host_cmd_host_event_commands, test_host_event_get_b)
+{
+#ifdef CONFIG_HOSTCMD_X86
+ struct ec_response_host_event_mask result = { 0 };
+
+ host_event_get_b_helper(&result);
+#else
+ ztest_test_skip();
+#endif
+}
+
+static void
+host_event_get_sci_mask_helper(struct ec_response_host_event_mask *r)
+{
+ enum ec_status ret_val;
+ struct host_cmd_handler_args args = BUILD_HOST_COMMAND_RESPONSE(
+ EC_CMD_HOST_EVENT_GET_SCI_MASK, 0, *r);
+
+ ret_val = host_command_process(&args);
+
+ /* EC_CMD_HOST_EVENT_GET_SCI_MASK always returns success */
+ zassert_equal(ret_val, EC_RES_SUCCESS, "Expected %d, returned %d",
+ EC_RES_SUCCESS, ret_val);
+}
+
+static void host_event_set_sci_mask_helper(uint32_t mask)
+{
+ enum ec_status ret_val;
+ struct ec_params_host_event_mask params = { .mask = mask };
+ struct host_cmd_handler_args args = BUILD_HOST_COMMAND_PARAMS(
+ EC_CMD_HOST_EVENT_SET_SCI_MASK, 0, params);
+
+ ret_val = host_command_process(&args);
+
+ /* EC_CMD_HOST_EVENT_SET_SCI_MASK always returns success */
+ zassert_equal(ret_val, EC_RES_SUCCESS, "Expected %d, returned %d",
+ EC_RES_SUCCESS, ret_val);
+}
+
+/**
+ * @brief TestPurpose: Verify EC_CMD_HOST_EVENT_GET_SCI_MASK host command.
+ */
+ZTEST_USER(host_cmd_host_event_commands, test_host_event_get_sci_mask)
+{
+#ifdef CONFIG_HOSTCMD_X86
+ struct ec_response_host_event_mask result = { 0 };
+
+ host_event_get_sci_mask_helper(&result);
+#else
+ ztest_test_skip();
+#endif
+}
+
+/**
+ * @brief TestPurpose: Verify EC_CMD_HOST_EVENT_SET_SCI_MASK host command.
+ */
+ZTEST_USER(host_cmd_host_event_commands, test_host_event_set_sci_mask)
+{
+#ifdef CONFIG_HOSTCMD_X86
+ struct ec_response_host_event_mask result = { 0 };
+
+ /* Read the current mask */
+ host_event_get_sci_mask_helper(&result);
+
+ /* Default mask is expected to be clear */
+ zassert_false(result.mask, "Default host event SCI mask is not clear");
+
+ host_event_set_sci_mask_helper(HOST_EVENT_TEST_MASK_VAL);
+
+ /* Verify the mask changed */
+ host_event_get_sci_mask_helper(&result);
+
+ zassert_equal(result.mask, HOST_EVENT_TEST_MASK_VAL,
+ "Expected SCI mask 0x%08x, returned mask 0x%08x",
+ HOST_EVENT_TEST_MASK_VAL, result.mask);
+
+ /* Clean up the mask */
+ host_event_set_sci_mask_helper(0);
+#else
+ ztest_test_skip();
+#endif
+}
diff --git a/zephyr/test/drivers/host_cmd/src/keyboard_mkbp.c b/zephyr/test/drivers/host_cmd/src/keyboard_mkbp.c
new file mode 100644
index 0000000000..4c74a48ab4
--- /dev/null
+++ b/zephyr/test/drivers/host_cmd/src/keyboard_mkbp.c
@@ -0,0 +1,81 @@
+/* Copyright 2022 The ChromiumOS Authors
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include <zephyr/ztest.h>
+#include "include/keyboard_mkbp.h"
+#include "test/drivers/test_state.h"
+#include "test/drivers/utils.h"
+
+struct keyboard_mkbp_commands_fixture {
+ struct ec_mkbp_config config;
+};
+
+static void *keyboard_mkbp_setup(void)
+{
+ static struct keyboard_mkbp_commands_fixture fixture = { 0 };
+
+ return &fixture;
+}
+
+static void keyboard_mkbp_before(void *fixture)
+{
+ struct keyboard_mkbp_commands_fixture *f = fixture;
+
+ get_keyscan_config(&f->config);
+}
+
+static void keyboard_mkbp_after(void *fixture)
+{
+ struct keyboard_mkbp_commands_fixture *f = fixture;
+ struct ec_params_mkbp_set_config req = { 0 };
+ struct host_cmd_handler_args args =
+ BUILD_HOST_COMMAND_PARAMS(EC_CMD_MKBP_SET_CONFIG, 0, req);
+
+ req.config = f->config;
+ host_command_process(&args);
+}
+
+ZTEST_SUITE(keyboard_mkbp_commands, drivers_predicate_post_main,
+ keyboard_mkbp_setup, keyboard_mkbp_before, keyboard_mkbp_after,
+ NULL);
+
+/**
+ * @brief TestPurpose: Verify EC_CMD_MKBP_GET_CONFIG host command.
+ */
+ZTEST_USER(keyboard_mkbp_commands, test_mkbp_get_config_cmd)
+{
+ enum ec_status ret_val;
+ struct ec_response_mkbp_get_config resp;
+
+ struct host_cmd_handler_args args =
+ BUILD_HOST_COMMAND_RESPONSE(EC_CMD_MKBP_GET_CONFIG, 0, resp);
+
+ ret_val = host_command_process(&args);
+
+ zassert_ok(ret_val, "Expected=%d, returned=%d", EC_SUCCESS, ret_val);
+}
+
+/**
+ * @brief TestPurpose: Verify EC_CMD_MKBP_SET_CONFIG host command.
+ */
+ZTEST_USER(keyboard_mkbp_commands, test_mkbp_set_config_cmd)
+{
+ enum ec_status ret_val;
+ struct ec_params_mkbp_set_config req = { 0 };
+ struct host_cmd_handler_args args =
+ BUILD_HOST_COMMAND_PARAMS(EC_CMD_MKBP_SET_CONFIG, 0, req);
+
+ get_keyscan_config(&req.config);
+
+ req.config.valid_mask =
+ EC_MKBP_VALID_SCAN_PERIOD | EC_MKBP_VALID_POLL_TIMEOUT |
+ EC_MKBP_VALID_MIN_POST_SCAN_DELAY |
+ EC_MKBP_VALID_OUTPUT_SETTLE | EC_MKBP_VALID_DEBOUNCE_DOWN |
+ EC_MKBP_VALID_DEBOUNCE_UP | EC_MKBP_VALID_FIFO_MAX_DEPTH;
+
+ ret_val = host_command_process(&args);
+
+ zassert_ok(ret_val, "Expected=%d, returned=%d", EC_SUCCESS, ret_val);
+}
diff --git a/zephyr/test/drivers/host_cmd/src/motion_sense.c b/zephyr/test/drivers/host_cmd/src/motion_sense.c
new file mode 100644
index 0000000000..c75f327fed
--- /dev/null
+++ b/zephyr/test/drivers/host_cmd/src/motion_sense.c
@@ -0,0 +1,868 @@
+/* Copyright 2022 The ChromiumOS Authors
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include <zephyr/fff.h>
+#include <zephyr/shell/shell.h>
+#include <zephyr/ztest.h>
+
+#include "atomic.h"
+#include "console.h"
+#include "driver/accel_bma2x2.h"
+#include "motion_sense.h"
+#include "motion_sense_fifo.h"
+#include "test/drivers/test_state.h"
+#include "test/drivers/utils.h"
+
+FAKE_VALUE_FUNC(int, mock_set_range, struct motion_sensor_t *, int, int);
+FAKE_VALUE_FUNC(int, mock_set_offset, const struct motion_sensor_t *,
+ const int16_t *, int16_t);
+FAKE_VALUE_FUNC(int, mock_get_offset, const struct motion_sensor_t *, int16_t *,
+ int16_t *);
+FAKE_VALUE_FUNC(int, mock_set_scale, const struct motion_sensor_t *,
+ const uint16_t *, int16_t);
+FAKE_VALUE_FUNC(int, mock_get_scale, const struct motion_sensor_t *, uint16_t *,
+ int16_t *);
+FAKE_VALUE_FUNC(int, mock_perform_calib, struct motion_sensor_t *, int);
+
+/**
+ * Get the size needed for a struct ec_response_motion_sense
+ */
+#define RESPONSE_MOTION_SENSE_BUFFER_SIZE(n) \
+ (sizeof(struct ec_response_motion_sense) + \
+ n * sizeof(struct ec_response_motion_sensor_data))
+
+#define RESPONSE_SENSOR_FIFO_SIZE(n) \
+ (sizeof(struct ec_response_motion_sense) + n * sizeof(uint16_t))
+
+struct host_cmd_motion_sense_fixture {
+ const struct accelgyro_drv *sensor_0_drv;
+ struct accelgyro_drv mock_drv;
+};
+
+static void *host_cmd_motion_sense_setup(void)
+{
+ static struct host_cmd_motion_sense_fixture fixture = {
+ .mock_drv = {
+ .set_range = mock_set_range,
+ .set_offset = mock_set_offset,
+ .get_offset = mock_get_offset,
+ .set_scale = mock_set_scale,
+ .get_scale = mock_get_scale,
+ .perform_calib = mock_perform_calib,
+ },
+ };
+
+ fixture.sensor_0_drv = motion_sensors[0].drv;
+
+ return &fixture;
+}
+
+static void host_cmd_motion_sense_before(void *fixture)
+{
+ ARG_UNUSED(fixture);
+ RESET_FAKE(mock_set_range);
+ RESET_FAKE(mock_set_offset);
+ RESET_FAKE(mock_get_offset);
+ RESET_FAKE(mock_set_scale);
+ RESET_FAKE(mock_get_scale);
+ RESET_FAKE(mock_perform_calib);
+ FFF_RESET_HISTORY();
+
+ zassume_ok(shell_execute_cmd(get_ec_shell(), "accelinit 0"), NULL);
+
+ atomic_clear(&motion_sensors[0].flush_pending);
+ motion_sensors[0].config[SENSOR_CONFIG_AP].odr = 0;
+ motion_sensors[0].config[SENSOR_CONFIG_AP].ec_rate = 1000 * MSEC;
+}
+
+static void host_cmd_motion_sense_after(void *fixture)
+{
+ struct host_cmd_motion_sense_fixture *this = fixture;
+ struct ec_response_motion_sense response;
+
+ motion_sensors[0].drv = this->sensor_0_drv;
+ host_cmd_motion_sense_int_enable(0, &response);
+ motion_sensors[0].flags &= ~MOTIONSENSE_FLAG_IN_SPOOF_MODE;
+ motion_sensors[0].config[SENSOR_CONFIG_AP].odr = 0;
+ motion_sensors[0].config[SENSOR_CONFIG_AP].ec_rate = 1000 * MSEC;
+}
+
+ZTEST_SUITE(host_cmd_motion_sense, drivers_predicate_post_main,
+ host_cmd_motion_sense_setup, host_cmd_motion_sense_before,
+ host_cmd_motion_sense_after, NULL);
+
+ZTEST_USER(host_cmd_motion_sense, test_dump)
+{
+ uint8_t response_buffer[RESPONSE_MOTION_SENSE_BUFFER_SIZE(
+ ALL_MOTION_SENSORS)];
+ struct ec_response_motion_sense *result =
+ (struct ec_response_motion_sense *)response_buffer;
+
+ /* Set up the motion sensor data */
+ for (int i = 0; i < ALL_MOTION_SENSORS; ++i) {
+ motion_sensors[i].xyz[0] = i;
+ motion_sensors[i].xyz[1] = i + 1;
+ motion_sensors[i].xyz[2] = i + 2;
+ }
+
+ /* Make sure that the accelerometer status presence bit is off */
+ *host_get_memmap(EC_MEMMAP_ACC_STATUS) &=
+ ~(EC_MEMMAP_ACC_STATUS_PRESENCE_BIT);
+
+ /* Dump all the sensors info */
+ host_cmd_motion_sense_dump(ALL_MOTION_SENSORS, result);
+
+ zassert_equal(result->dump.module_flags, 0, NULL);
+ zassert_equal(result->dump.sensor_count, ALL_MOTION_SENSORS, NULL);
+
+ /*
+ * Test the values returned in the dump. Normally we shouldn't be doing
+ * tests in a loop, but since the number of sensors (as well as the
+ * order) is adjustable by devicetree, it would be too difficult to hard
+ * code here.
+ */
+ for (int i = 0; i < ALL_MOTION_SENSORS; ++i) {
+ zassert_equal(result->dump.sensor[i].flags,
+ MOTIONSENSE_SENSOR_FLAG_PRESENT, NULL);
+ zassert_equal(result->dump.sensor[i].data[0], i, NULL);
+ zassert_equal(result->dump.sensor[i].data[1], i + 1, NULL);
+ zassert_equal(result->dump.sensor[i].data[2], i + 2, NULL);
+ }
+
+ /* Make sure that the accelerometer status presence bit is on */
+ *host_get_memmap(EC_MEMMAP_ACC_STATUS) |=
+ EC_MEMMAP_ACC_STATUS_PRESENCE_BIT;
+
+ /* Dump all the sensors info */
+ host_cmd_motion_sense_dump(ALL_MOTION_SENSORS, result);
+
+ zassert_equal(result->dump.module_flags, MOTIONSENSE_MODULE_FLAG_ACTIVE,
+ NULL);
+}
+
+ZTEST_USER(host_cmd_motion_sense, test_dump__large_max_sensor_count)
+{
+ uint8_t response_buffer[RESPONSE_MOTION_SENSE_BUFFER_SIZE(
+ ALL_MOTION_SENSORS)];
+ struct ec_response_motion_sense *result =
+ (struct ec_response_motion_sense *)response_buffer;
+
+ host_cmd_motion_sense_dump(ALL_MOTION_SENSORS + 1, result);
+
+ zassert_equal(result->dump.sensor_count, ALL_MOTION_SENSORS, NULL);
+}
+
+ZTEST_USER(host_cmd_motion_sense, test_read_data__invalid_sensor_num)
+{
+ struct ec_response_motion_sense response;
+
+ zassert_equal(host_cmd_motion_sense_data(UINT8_MAX, &response),
+ EC_RES_INVALID_PARAM, NULL);
+}
+
+ZTEST_USER(host_cmd_motion_sense, test_read_data)
+{
+ struct ec_response_motion_sense response;
+
+ motion_sensors[0].xyz[0] = 1;
+ motion_sensors[0].xyz[1] = 2;
+ motion_sensors[0].xyz[2] = 3;
+
+ zassert_ok(host_cmd_motion_sense_data(0, &response), NULL);
+ zassert_equal(response.data.flags, 0, NULL);
+ zassert_equal(response.data.data[0], 1, NULL);
+ zassert_equal(response.data.data[1], 2, NULL);
+ zassert_equal(response.data.data[2], 3, NULL);
+}
+
+ZTEST_USER(host_cmd_motion_sense, test_get_info__invalid_sensor_num)
+{
+ struct ec_response_motion_sense response;
+
+ zassert_equal(host_cmd_motion_sense_info(/*cmd_version=*/1,
+ /*sensor_num=*/UINT8_MAX,
+ &response),
+ EC_RES_INVALID_PARAM, NULL);
+}
+
+ZTEST_USER(host_cmd_motion_sense, test_get_info_v1)
+{
+ struct ec_response_motion_sense response;
+
+ zassert_ok(host_cmd_motion_sense_info(/*cmd_version=*/1,
+ /*sensor_num=*/0, &response),
+ NULL);
+ zassert_equal(response.info.type, motion_sensors[0].type, NULL);
+ zassert_equal(response.info.location, motion_sensors[0].location, NULL);
+ zassert_equal(response.info.chip, motion_sensors[0].chip, NULL);
+}
+
+ZTEST_USER(host_cmd_motion_sense, test_get_info_v3)
+{
+ struct ec_response_motion_sense response;
+
+ zassert_ok(host_cmd_motion_sense_info(/*cmd_version=*/3,
+ /*sensor_num=*/0, &response),
+ NULL);
+ zassert_equal(response.info.type, motion_sensors[0].type, NULL);
+ zassert_equal(response.info.location, motion_sensors[0].location, NULL);
+ zassert_equal(response.info.chip, motion_sensors[0].chip, NULL);
+ zassert_equal(response.info_3.min_frequency,
+ motion_sensors[0].min_frequency, NULL);
+ zassert_equal(response.info_3.max_frequency,
+ motion_sensors[0].max_frequency, NULL);
+ zassert_equal(response.info_3.fifo_max_event_count,
+ CONFIG_ACCEL_FIFO_SIZE, NULL);
+}
+
+ZTEST_USER(host_cmd_motion_sense, test_get_info_v4__no_read_temp)
+{
+ struct ec_response_motion_sense response;
+
+ zassert_ok(host_cmd_motion_sense_info(/*cmd_version=*/4,
+ /*sensor_num=*/0, &response),
+ NULL);
+ zassert_equal(response.info.type, motion_sensors[0].type, NULL);
+ zassert_equal(response.info.location, motion_sensors[0].location, NULL);
+ zassert_equal(response.info.chip, motion_sensors[0].chip, NULL);
+ if (IS_ENABLED(CONFIG_ONLINE_CALIB)) {
+ zassert_true(response.info_4.flags &
+ MOTION_SENSE_CMD_INFO_FLAG_ONLINE_CALIB,
+ NULL);
+ } else {
+ zassert_false(response.info_4.flags &
+ MOTION_SENSE_CMD_INFO_FLAG_ONLINE_CALIB,
+ NULL);
+ }
+}
+
+ZTEST_USER(host_cmd_motion_sense, test_get_ec_rate__invalid_sensor_num)
+{
+ struct ec_response_motion_sense response;
+
+ zassert_equal(host_cmd_motion_sense_ec_rate(
+ /*sensor_num=*/0xff,
+ /*data_rate_ms=*/EC_MOTION_SENSE_NO_VALUE,
+ &response),
+ EC_RES_INVALID_PARAM, NULL);
+}
+
+ZTEST_USER(host_cmd_motion_sense, test_get_ec_rate)
+{
+ struct ec_response_motion_sense response;
+
+ /* Set the power level to S3, the default config from device-tree is for
+ * 100ms
+ */
+ test_set_chipset_to_power_level(POWER_S3);
+ zassert_ok(host_cmd_motion_sense_ec_rate(
+ /*sensor_num=*/0,
+ /*data_rate_ms=*/EC_MOTION_SENSE_NO_VALUE,
+ &response),
+ NULL);
+ zassert_equal(response.ec_rate.ret, 1000, NULL);
+}
+
+ZTEST_USER(host_cmd_motion_sense, test_set_ec_rate)
+{
+ struct ec_response_motion_sense response;
+
+ /* Set the power level to S3, the default config from device-tree is for
+ * 100ms
+ */
+ test_set_chipset_to_power_level(POWER_S3);
+ zassert_ok(host_cmd_motion_sense_ec_rate(
+ /*sensor_num=*/0, /*data_rate_ms=*/2000, &response),
+ NULL);
+ /* The command should return the previous rate */
+ zassert_equal(response.ec_rate.ret, 1000, "Expected 1000, but got %d",
+ response.ec_rate.ret);
+ /* The sensor's AP config value should be updated */
+ zassert_equal(motion_sensors[0].config[SENSOR_CONFIG_AP].ec_rate,
+ 2000 * MSEC, NULL);
+}
+
+ZTEST_USER(host_cmd_motion_sense, test_odr_invalid_sensor_num)
+{
+ struct ec_response_motion_sense response;
+
+ zassert_equal(EC_RES_INVALID_PARAM,
+ host_cmd_motion_sense_odr(
+ /*sensor_num=*/0xff,
+ /*odr=*/EC_MOTION_SENSE_NO_VALUE,
+ /*round_up=*/false, &response),
+ NULL);
+}
+
+ZTEST_USER(host_cmd_motion_sense, test_odr_get)
+{
+ struct ec_response_motion_sense response;
+
+ zassume_ok(motion_sensors[0].drv->set_data_rate(&motion_sensors[0],
+ 1000000, false),
+ NULL);
+ zassert_ok(host_cmd_motion_sense_odr(/*sensor_num=*/0,
+ /*odr=*/EC_MOTION_SENSE_NO_VALUE,
+ /*round_up=*/false, &response),
+ NULL);
+ zassert_equal(BMA2x2_REG_TO_BW(BMA2x2_BW_1000HZ),
+ response.sensor_odr.ret, "Expected %d, but got %d",
+ BMA2x2_REG_TO_BW(BMA2x2_BW_1000HZ),
+ response.sensor_odr.ret);
+}
+
+ZTEST_USER(host_cmd_motion_sense, test_odr_set)
+{
+ struct ec_response_motion_sense response;
+
+ zassume_ok(motion_sensors[0].drv->set_data_rate(&motion_sensors[0], 0,
+ false),
+ NULL);
+ zassert_ok(host_cmd_motion_sense_odr(/*sensor_num=*/0,
+ /*odr=*/1000000,
+ /*round_up=*/true, &response),
+ NULL);
+ /* Check the set value */
+ zassert_equal(1000000 | ROUND_UP_FLAG,
+ motion_sensors[0].config[SENSOR_CONFIG_AP].odr,
+ "Expected %d, but got %d", 1000000 | ROUND_UP_FLAG,
+ motion_sensors[0].config[SENSOR_CONFIG_AP].odr);
+ /* Check the returned value */
+ zassert_equal(BMA2x2_REG_TO_BW(BMA2x2_BW_7_81HZ),
+ response.sensor_odr.ret, "Expected %d, but got %d",
+ BMA2x2_REG_TO_BW(BMA2x2_BW_7_81HZ),
+ response.sensor_odr.ret);
+}
+
+ZTEST_USER(host_cmd_motion_sense, test_range_invalid_sensor_num)
+{
+ struct ec_response_motion_sense response;
+
+ zassert_equal(EC_RES_INVALID_PARAM,
+ host_cmd_motion_sense_range(
+ /*sensor_num=*/0xff,
+ /*range=*/EC_MOTION_SENSE_NO_VALUE,
+ /*round_up=*/false, &response),
+ NULL);
+}
+
+ZTEST_USER(host_cmd_motion_sense, test_get_range)
+{
+ struct ec_response_motion_sense response;
+
+ zassert_ok(host_cmd_motion_sense_range(
+ /*sensor_num=*/0, /*range=*/EC_MOTION_SENSE_NO_VALUE,
+ /*round_up=*/false, &response),
+ NULL);
+ zassert_equal(motion_sensors[0].current_range,
+ response.sensor_range.ret, "Expected %d, but got %d",
+ motion_sensors[0].current_range,
+ response.sensor_range.ret);
+}
+
+ZTEST_USER(host_cmd_motion_sense, test_null_set_range_in_driver)
+{
+ struct ec_response_motion_sense response;
+ struct accelgyro_drv drv = { 0 };
+
+ motion_sensors[0].drv = &drv;
+ zassert_equal(EC_RES_INVALID_COMMAND,
+ host_cmd_motion_sense_range(/*sensor_num=*/0, /*range=*/4,
+ /*round_up=*/false,
+ &response),
+ NULL);
+}
+
+ZTEST_USER_F(host_cmd_motion_sense, test_set_range_error)
+{
+ struct ec_response_motion_sense response;
+
+ mock_set_range_fake.return_val = 1;
+ motion_sensors[0].drv = &fixture->mock_drv;
+
+ zassert_equal(EC_RES_INVALID_PARAM,
+ host_cmd_motion_sense_range(/*sensor_num=*/0, /*range=*/4,
+ /*round_up=*/false,
+ &response),
+ NULL);
+ zassert_equal(1, mock_set_range_fake.call_count, NULL);
+}
+
+ZTEST_USER_F(host_cmd_motion_sense, test_set_range)
+{
+ struct ec_response_motion_sense response;
+
+ mock_set_range_fake.return_val = 0;
+ motion_sensors[0].drv = &fixture->mock_drv;
+
+ zassert_ok(host_cmd_motion_sense_range(/*sensor_num=*/0, /*range=*/4,
+ /*round_up=*/false, &response),
+ NULL);
+ zassert_equal(1, mock_set_range_fake.call_count, NULL);
+ zassert_equal(4, mock_set_range_fake.arg1_history[0], NULL);
+ zassert_equal(0, mock_set_range_fake.arg2_history[0], NULL);
+}
+
+ZTEST_USER(host_cmd_motion_sense, test_offset_invalid_sensor_num)
+{
+ struct ec_response_motion_sense response;
+
+ zassert_equal(EC_RES_INVALID_PARAM,
+ host_cmd_motion_sense_offset(
+ /*sensor_num=*/0xff, /*flags=*/0,
+ /*temperature=*/0, /*offset_x=*/0,
+ /*offset_y=*/0, /*offset_z=*/0, &response),
+ NULL);
+}
+
+ZTEST_USER(host_cmd_motion_sense, test_offset_missing_get_offset_in_driver)
+{
+ struct ec_response_motion_sense response;
+ struct accelgyro_drv drv = { 0 };
+
+ motion_sensors[0].drv = &drv;
+
+ zassert_equal(EC_RES_INVALID_COMMAND,
+ host_cmd_motion_sense_offset(
+ /*sensor_num=*/0, /*flags=*/0,
+ /*temperature=*/0, /*offset_x=*/0,
+ /*offset_y=*/0, /*offset_z=*/0, &response),
+ NULL);
+}
+
+ZTEST_USER(host_cmd_motion_sense, test_offset_missing_set_offset_in_driver)
+{
+ struct ec_response_motion_sense response;
+ struct accelgyro_drv drv = { 0 };
+
+ motion_sensors[0].drv = &drv;
+
+ zassert_equal(EC_RES_INVALID_COMMAND,
+ host_cmd_motion_sense_offset(
+ /*sensor_num=*/0,
+ /*flags=*/MOTION_SENSE_SET_OFFSET,
+ /*temperature=*/0, /*offset_x=*/0,
+ /*offset_y=*/0, /*offset_z=*/0, &response),
+ NULL);
+}
+
+ZTEST_USER_F(host_cmd_motion_sense, test_offset_fail_to_set)
+{
+ struct ec_response_motion_sense response;
+
+ motion_sensors[0].drv = &fixture->mock_drv;
+ mock_set_offset_fake.return_val = EC_RES_ERROR;
+
+ zassert_equal(EC_RES_ERROR,
+ host_cmd_motion_sense_offset(
+ /*sensor_num=*/0,
+ /*flags=*/MOTION_SENSE_SET_OFFSET,
+ /*temperature=*/0, /*offset_x=*/0,
+ /*offset_y=*/0, /*offset_z=*/0, &response),
+ NULL);
+ zassert_equal(1, mock_set_offset_fake.call_count, NULL);
+}
+
+ZTEST_USER_F(host_cmd_motion_sense, test_offset_fail_to_get)
+{
+ struct ec_response_motion_sense response;
+
+ motion_sensors[0].drv = &fixture->mock_drv;
+ mock_set_offset_fake.return_val = EC_RES_SUCCESS;
+ mock_get_offset_fake.return_val = EC_RES_ERROR;
+
+ zassert_equal(EC_RES_ERROR,
+ host_cmd_motion_sense_offset(
+ /*sensor_num=*/0,
+ /*flags=*/MOTION_SENSE_SET_OFFSET,
+ /*temperature=*/0, /*offset_x=*/0,
+ /*offset_y=*/0, /*offset_z=*/0, &response),
+ NULL);
+ zassert_equal(1, mock_set_offset_fake.call_count, NULL);
+ zassert_equal(1, mock_get_offset_fake.call_count, NULL);
+ zassert_equal((int16_t *)&response.sensor_offset.offset,
+ mock_get_offset_fake.arg1_history[0], NULL);
+}
+
+ZTEST_USER_F(host_cmd_motion_sense, test_get_offset)
+{
+ struct ec_response_motion_sense response;
+
+ motion_sensors[0].drv = &fixture->mock_drv;
+ mock_get_offset_fake.return_val = EC_RES_SUCCESS;
+ mock_set_offset_fake.return_val = EC_RES_SUCCESS;
+
+ zassert_ok(host_cmd_motion_sense_offset(
+ /*sensor_num=*/0,
+ /*flags=*/MOTION_SENSE_SET_OFFSET,
+ /*temperature=*/1, /*offset_x=*/2,
+ /*offset_y=*/3, /*offset_z=*/4, &response),
+ NULL);
+ zassert_equal(1, mock_set_offset_fake.call_count, NULL);
+ zassert_equal(1, mock_get_offset_fake.call_count, NULL);
+ zassert_equal((int16_t *)&response.sensor_offset.offset,
+ mock_get_offset_fake.arg1_history[0], NULL);
+ zassert_equal(1, mock_set_offset_fake.arg2_history[0], NULL);
+}
+
+ZTEST_USER(host_cmd_motion_sense, test_scale_invalid_sensor_num)
+{
+ struct ec_response_motion_sense response;
+
+ zassert_equal(EC_RES_INVALID_PARAM,
+ host_cmd_motion_sense_scale(
+ /*sensor_num=*/0xff,
+ /*flags=*/0,
+ /*temperature=*/1, /*scale_x=*/2,
+ /*scale_y=*/3, /*scale_z=*/4, &response),
+ NULL);
+}
+
+ZTEST_USER(host_cmd_motion_sense, test_get_scale_not_in_driver)
+{
+ struct ec_response_motion_sense response;
+ struct accelgyro_drv drv = *motion_sensors[0].drv;
+
+ drv.get_scale = NULL;
+ motion_sensors[0].drv = &drv;
+
+ zassert_equal(EC_RES_INVALID_COMMAND,
+ host_cmd_motion_sense_scale(
+ /*sensor_num=*/0,
+ /*flags=*/0,
+ /*temperature=*/1, /*scale_x=*/2,
+ /*scale_y=*/3, /*scale_z=*/4, &response),
+ NULL);
+}
+
+ZTEST_USER(host_cmd_motion_sense, test_set_scale_not_in_driver)
+{
+ struct ec_response_motion_sense response;
+ struct accelgyro_drv drv = *motion_sensors[0].drv;
+
+ drv.set_scale = NULL;
+ motion_sensors[0].drv = &drv;
+
+ zassert_equal(EC_RES_INVALID_COMMAND,
+ host_cmd_motion_sense_scale(
+ /*sensor_num=*/0,
+ /*flags=*/MOTION_SENSE_SET_OFFSET,
+ /*temperature=*/1, /*scale_x=*/2,
+ /*scale_y=*/3, /*scale_z=*/4, &response),
+ NULL);
+}
+
+ZTEST_USER_F(host_cmd_motion_sense, test_get_scale_fail)
+{
+ struct ec_response_motion_sense response;
+
+ motion_sensors[0].drv = &fixture->mock_drv;
+ mock_get_scale_fake.return_val = 1;
+
+ zassert_equal(1,
+ host_cmd_motion_sense_scale(
+ /*sensor_num=*/0,
+ /*flags=*/0,
+ /*temperature=*/1, /*scale_x=*/2,
+ /*scale_y=*/3, /*scale_z=*/4, &response),
+ NULL);
+ zassert_equal(1, mock_get_scale_fake.call_count, NULL);
+}
+
+ZTEST_USER_F(host_cmd_motion_sense, test_set_scale_fail)
+{
+ struct ec_response_motion_sense response;
+
+ motion_sensors[0].drv = &fixture->mock_drv;
+ mock_set_scale_fake.return_val = 1;
+
+ zassert_equal(1,
+ host_cmd_motion_sense_scale(
+ /*sensor_num=*/0,
+ /*flags=*/MOTION_SENSE_SET_OFFSET,
+ /*temperature=*/1, /*scale_x=*/2,
+ /*scale_y=*/3, /*scale_z=*/4, &response),
+ NULL);
+ zassert_equal(1, mock_set_scale_fake.call_count, NULL);
+}
+
+ZTEST_USER_F(host_cmd_motion_sense, test_set_get_scale)
+{
+ struct ec_response_motion_sense response;
+
+ motion_sensors[0].drv = &fixture->mock_drv;
+ mock_set_scale_fake.return_val = 0;
+ mock_get_scale_fake.return_val = 0;
+
+ zassert_ok(host_cmd_motion_sense_scale(
+ /*sensor_num=*/0,
+ /*flags=*/MOTION_SENSE_SET_OFFSET,
+ /*temperature=*/1, /*scale_x=*/2,
+ /*scale_y=*/3, /*scale_z=*/4, &response),
+ NULL);
+ zassert_equal(1, mock_set_scale_fake.call_count, NULL);
+ zassert_equal(1, mock_get_scale_fake.call_count, NULL);
+ zassert_equal(1, mock_set_scale_fake.arg2_history[0], NULL);
+}
+
+ZTEST_USER(host_cmd_motion_sense, test_calib_invalid_sensor_num)
+{
+ struct ec_response_motion_sense response;
+
+ zassert_equal(EC_RES_INVALID_PARAM,
+ host_cmd_motion_sense_calib(/*sensor_num=*/0xff,
+ /*enable=*/false, &response),
+ NULL);
+}
+
+ZTEST_USER(host_cmd_motion_sense, test_calib_not_in_driver)
+{
+ struct ec_response_motion_sense response;
+ struct accelgyro_drv drv = { 0 };
+
+ motion_sensors[0].drv = &drv;
+ zassert_equal(EC_RES_INVALID_COMMAND,
+ host_cmd_motion_sense_calib(/*sensor_num=*/0,
+ /*enable=*/false, &response),
+ NULL);
+}
+
+ZTEST_USER_F(host_cmd_motion_sense, test_calib_fail)
+{
+ struct ec_response_motion_sense response;
+
+ motion_sensors[0].drv = &fixture->mock_drv;
+ mock_perform_calib_fake.return_val = 1;
+
+ zassert_equal(1,
+ host_cmd_motion_sense_calib(/*sensor_num=*/0,
+ /*enable=*/false, &response),
+ NULL);
+ zassert_equal(1, mock_perform_calib_fake.call_count, NULL);
+ zassert_false(mock_perform_calib_fake.arg1_history[0], NULL);
+}
+
+ZTEST_USER_F(host_cmd_motion_sense, test_calib_success__fail_get_offset)
+{
+ struct ec_response_motion_sense response;
+
+ motion_sensors[0].drv = &fixture->mock_drv;
+ mock_perform_calib_fake.return_val = 0;
+ mock_get_offset_fake.return_val = 1;
+
+ zassert_equal(1,
+ host_cmd_motion_sense_calib(/*sensor_num=*/0,
+ /*enable=*/false, &response),
+ NULL);
+ zassert_equal(1, mock_perform_calib_fake.call_count, NULL);
+ zassert_equal(1, mock_get_offset_fake.call_count, NULL);
+ zassert_false(mock_perform_calib_fake.arg1_history[0], NULL);
+}
+
+ZTEST_USER_F(host_cmd_motion_sense, test_calib)
+{
+ struct ec_response_motion_sense response;
+
+ motion_sensors[0].drv = &fixture->mock_drv;
+ mock_perform_calib_fake.return_val = 0;
+ mock_get_offset_fake.return_val = 0;
+
+ zassert_ok(host_cmd_motion_sense_calib(/*sensor_num=*/0,
+ /*enable=*/true, &response),
+ NULL);
+ zassert_equal(1, mock_perform_calib_fake.call_count, NULL);
+ zassert_equal(1, mock_get_offset_fake.call_count, NULL);
+ zassert_true(mock_perform_calib_fake.arg1_history[0], NULL);
+}
+
+ZTEST(host_cmd_motion_sense, test_fifo_flush__invalid_sensor_num)
+{
+ int rv;
+ struct ec_response_motion_sense response;
+
+ rv = host_cmd_motion_sense_fifo_flush(/*sensor_num=*/0xff, &response);
+ zassert_equal(rv, EC_RES_INVALID_PARAM, NULL);
+}
+
+ZTEST(host_cmd_motion_sense, test_fifo_flush)
+{
+ uint8_t response_buffer[RESPONSE_SENSOR_FIFO_SIZE(ALL_MOTION_SENSORS)];
+ struct ec_response_motion_sense *response =
+ (struct ec_response_motion_sense *)response_buffer;
+
+ zassert_ok(host_cmd_motion_sense_fifo_flush(/*sensor_num=*/0, response),
+ NULL);
+ zassert_equal(1, motion_sensors[0].flush_pending, NULL);
+}
+
+ZTEST(host_cmd_motion_sense, test_fifo_info)
+{
+ uint8_t response_buffer[RESPONSE_SENSOR_FIFO_SIZE(ALL_MOTION_SENSORS)];
+ struct ec_response_motion_sense *response =
+ (struct ec_response_motion_sense *)response_buffer;
+
+ zassert_ok(host_cmd_motion_sense_fifo_info(response), NULL);
+}
+
+ZTEST(host_cmd_motion_sense, test_fifo_read)
+{
+ struct ec_response_motion_sensor_data data;
+ uint8_t response_buffer[RESPONSE_MOTION_SENSE_BUFFER_SIZE(2)];
+ struct ec_response_motion_sense *response =
+ (struct ec_response_motion_sense *)response_buffer;
+
+ motion_sensors[0].oversampling_ratio = 1;
+ motion_sensors[1].oversampling_ratio = 1;
+
+ data = (struct ec_response_motion_sensor_data){
+ .flags = 0,
+ .sensor_num = 0,
+ .data = { 0, 1, 2 },
+ };
+ motion_sense_fifo_stage_data(&data, &motion_sensors[0], 1, 0);
+
+ data = (struct ec_response_motion_sensor_data){
+ .flags = 0,
+ .sensor_num = 1,
+ .data = { 3, 4, 5 },
+ };
+ motion_sense_fifo_stage_data(&data, &motion_sensors[1], 1, 5);
+ motion_sense_fifo_commit_data();
+
+ /* Read 2 samples */
+ zassert_ok(host_cmd_motion_sense_fifo_read(4, response), NULL);
+ zassert_equal(2, response->fifo_read.number_data, NULL);
+
+ zassert_equal(MOTIONSENSE_SENSOR_FLAG_TIMESTAMP,
+ response->fifo_read.data[0].flags, NULL);
+ zassert_equal(0, response->fifo_read.data[0].sensor_num, NULL);
+ zassert_equal(0, response->fifo_read.data[0].timestamp, NULL);
+
+ zassert_equal(0, response->fifo_read.data[1].flags, NULL);
+ zassert_equal(0, response->fifo_read.data[1].sensor_num, NULL);
+ zassert_equal(0, response->fifo_read.data[1].data[0], NULL);
+ zassert_equal(1, response->fifo_read.data[1].data[1], NULL);
+ zassert_equal(2, response->fifo_read.data[1].data[2], NULL);
+
+ /* Read the next 2 samples */
+ zassert_ok(host_cmd_motion_sense_fifo_read(4, response), NULL);
+ zassert_equal(2, response->fifo_read.number_data, NULL);
+ zassert_equal(MOTIONSENSE_SENSOR_FLAG_TIMESTAMP,
+ response->fifo_read.data[0].flags, NULL);
+ zassert_equal(1, response->fifo_read.data[0].sensor_num, NULL);
+ zassert_equal(5, response->fifo_read.data[0].timestamp, NULL);
+
+ zassert_equal(0, response->fifo_read.data[1].flags, NULL);
+ zassert_equal(1, response->fifo_read.data[1].sensor_num, NULL);
+ zassert_equal(3, response->fifo_read.data[1].data[0], NULL);
+ zassert_equal(4, response->fifo_read.data[1].data[1], NULL);
+ zassert_equal(5, response->fifo_read.data[1].data[2], NULL);
+}
+
+ZTEST(host_cmd_motion_sense, test_int_enable)
+{
+ struct ec_response_motion_sense response;
+
+ zassert_equal(EC_RES_INVALID_PARAM,
+ host_cmd_motion_sense_int_enable(2, &response), NULL);
+
+ /* Make sure we start off disabled */
+ zassume_ok(host_cmd_motion_sense_int_enable(0, &response), NULL);
+
+ /* Test enable */
+ zassert_ok(host_cmd_motion_sense_int_enable(1, &response), NULL);
+ zassert_ok(host_cmd_motion_sense_int_enable(EC_MOTION_SENSE_NO_VALUE,
+ &response),
+ NULL);
+ zassert_equal(1, response.fifo_int_enable.ret, NULL);
+
+ /* Test disable */
+ zassert_ok(host_cmd_motion_sense_int_enable(0, &response), NULL);
+ zassert_ok(host_cmd_motion_sense_int_enable(EC_MOTION_SENSE_NO_VALUE,
+ &response),
+ NULL);
+ zassert_equal(0, response.fifo_int_enable.ret, NULL);
+}
+
+ZTEST(host_cmd_motion_sense, test_spoof_invalid_sensor_num)
+{
+ struct ec_response_motion_sense response;
+
+ zassert_equal(EC_RES_INVALID_PARAM,
+ host_cmd_motion_sense_spoof(0xff, 0, 0, 0, 0, &response),
+ NULL);
+}
+
+ZTEST(host_cmd_motion_sense, test_spoof_disable)
+{
+ struct ec_response_motion_sense response;
+
+ motion_sensors[0].flags |= MOTIONSENSE_FLAG_IN_SPOOF_MODE;
+ zassert_ok(host_cmd_motion_sense_spoof(0,
+ MOTIONSENSE_SPOOF_MODE_DISABLE,
+ 0, 0, 0, &response),
+ NULL);
+ zassert_equal(0,
+ motion_sensors[0].flags & MOTIONSENSE_FLAG_IN_SPOOF_MODE,
+ NULL);
+
+ zassert_ok(host_cmd_motion_sense_spoof(0, MOTIONSENSE_SPOOF_MODE_QUERY,
+ 0, 0, 0, &response),
+ NULL);
+ zassert_false(response.spoof.ret, NULL);
+}
+
+ZTEST(host_cmd_motion_sense, test_spoof_custom)
+{
+ struct ec_response_motion_sense response;
+
+ zassert_ok(host_cmd_motion_sense_spoof(0, MOTIONSENSE_SPOOF_MODE_CUSTOM,
+ -8, 16, -32, &response),
+ NULL);
+ zassert_equal(MOTIONSENSE_FLAG_IN_SPOOF_MODE,
+ motion_sensors[0].flags & MOTIONSENSE_FLAG_IN_SPOOF_MODE,
+ NULL);
+ zassert_equal(-8, motion_sensors[0].spoof_xyz[0], NULL);
+ zassert_equal(16, motion_sensors[0].spoof_xyz[1], NULL);
+ zassert_equal(-32, motion_sensors[0].spoof_xyz[2], NULL);
+
+ zassert_ok(host_cmd_motion_sense_spoof(0, MOTIONSENSE_SPOOF_MODE_QUERY,
+ 0, 0, 0, &response),
+ NULL);
+ zassert_true(response.spoof.ret, NULL);
+}
+
+ZTEST(host_cmd_motion_sense, test_spoof_lock_current)
+{
+ struct ec_response_motion_sense response;
+
+ motion_sensors[0].raw_xyz[0] = 64;
+ motion_sensors[0].raw_xyz[1] = 48;
+ motion_sensors[0].raw_xyz[2] = 32;
+ zassert_ok(host_cmd_motion_sense_spoof(
+ 0, MOTIONSENSE_SPOOF_MODE_LOCK_CURRENT, 0, 0, 0,
+ &response),
+ NULL);
+ zassert_equal(MOTIONSENSE_FLAG_IN_SPOOF_MODE,
+ motion_sensors[0].flags & MOTIONSENSE_FLAG_IN_SPOOF_MODE,
+ NULL);
+ zassert_equal(64, motion_sensors[0].spoof_xyz[0], NULL);
+ zassert_equal(48, motion_sensors[0].spoof_xyz[1], NULL);
+ zassert_equal(32, motion_sensors[0].spoof_xyz[2], NULL);
+
+ zassert_ok(host_cmd_motion_sense_spoof(0, MOTIONSENSE_SPOOF_MODE_QUERY,
+ 0, 0, 0, &response),
+ NULL);
+ zassert_true(response.spoof.ret, NULL);
+}
+
+ZTEST(host_cmd_motion_sense, test_spoof_invalid_mode)
+{
+ struct ec_response_motion_sense response;
+
+ zassert_equal(EC_RES_INVALID_PARAM,
+ host_cmd_motion_sense_spoof(0, 0xff, 0, 0, 0, &response),
+ NULL);
+}
diff --git a/zephyr/test/drivers/host_cmd/src/pd_chip_info.c b/zephyr/test/drivers/host_cmd/src/pd_chip_info.c
new file mode 100644
index 0000000000..95e2339899
--- /dev/null
+++ b/zephyr/test/drivers/host_cmd/src/pd_chip_info.c
@@ -0,0 +1,65 @@
+/* Copyright 2022 The ChromiumOS Authors
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include <zephyr/shell/shell.h>
+#include <zephyr/ztest.h>
+
+#include "console.h"
+#include "ec_commands.h"
+#include "test/drivers/stubs.h"
+#include "test/drivers/test_state.h"
+#include "test/drivers/utils.h"
+
+#define TEST_PORT USBC_PORT_C0
+#define BAD_PORT 65
+
+static enum ec_status run_pd_chip_info(int port,
+ struct ec_response_pd_chip_info_v1 *resp)
+{
+ struct ec_params_pd_chip_info params = { .port = port, .live = true };
+ struct host_cmd_handler_args args =
+ BUILD_HOST_COMMAND(EC_CMD_PD_CHIP_INFO, 1, resp, params);
+
+ return host_command_process(&args);
+}
+
+ZTEST_USER(host_cmd_pd_chip_info, test_good_index)
+{
+ struct ec_response_pd_chip_info_v1 response;
+
+ zassert_ok(run_pd_chip_info(TEST_PORT, &response),
+ "Failed to process pd_get_chip_info for port %d", TEST_PORT);
+ /*
+ * Note: verification of the specific fields depends on the chips used
+ * and therefore would belong in a driver-level test
+ */
+}
+
+ZTEST_USER(host_cmd_pd_chip_info, test_bad_index)
+{
+ struct ec_response_pd_chip_info_v1 response;
+
+ zassume_true(board_get_usb_pd_port_count() < BAD_PORT,
+ "Intended bad port exists");
+ zassert_equal(run_pd_chip_info(BAD_PORT, &response),
+ EC_RES_INVALID_PARAM,
+ "Failed to fail pd_chip_info for port %d", BAD_PORT);
+}
+
+static void host_cmd_pd_chip_info_begin(void *data)
+{
+ ARG_UNUSED(data);
+
+ /* Assume we have at least one USB-C port */
+ zassume_true(board_get_usb_pd_port_count() > 0,
+ "Insufficient TCPCs found");
+
+ /* Set the system into S0, since the AP would drive these commands */
+ test_set_chipset_to_s0();
+ k_sleep(K_SECONDS(1));
+}
+
+ZTEST_SUITE(host_cmd_pd_chip_info, drivers_predicate_post_main, NULL,
+ host_cmd_pd_chip_info_begin, NULL, NULL);
diff --git a/zephyr/test/drivers/host_cmd/src/pd_control.c b/zephyr/test/drivers/host_cmd/src/pd_control.c
new file mode 100644
index 0000000000..e8de27f6ce
--- /dev/null
+++ b/zephyr/test/drivers/host_cmd/src/pd_control.c
@@ -0,0 +1,129 @@
+/* Copyright 2022 The ChromiumOS Authors
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include <zephyr/fff.h>
+#include <zephyr/shell/shell.h>
+#include <zephyr/ztest.h>
+
+#include "console.h"
+#include "ec_commands.h"
+#include "test/drivers/stubs.h"
+#include "test/drivers/test_state.h"
+#include "test/drivers/utils.h"
+
+#define TEST_PORT USBC_PORT_C0
+#define BAD_PORT 82
+
+ZTEST_USER(host_cmd_pd_control, test_bad_index)
+{
+ struct ec_params_pd_control params = { .chip = BAD_PORT,
+ .subcmd = PD_RESET };
+ struct host_cmd_handler_args args =
+ BUILD_HOST_COMMAND_PARAMS(EC_CMD_PD_CONTROL, 0, params);
+
+ zassume_true(board_get_usb_pd_port_count() < BAD_PORT,
+ "Intended bad port exists");
+ zassert_equal(host_command_process(&args), EC_RES_INVALID_PARAM,
+ "Failed to fail pd_control for port %d", params.chip);
+}
+
+ZTEST_USER(host_cmd_pd_control, test_unimplemented_command)
+{
+ struct ec_params_pd_control params = { .chip = TEST_PORT,
+ .subcmd = PD_CHIP_ON };
+ struct host_cmd_handler_args args =
+ BUILD_HOST_COMMAND_PARAMS(EC_CMD_PD_CONTROL, 0, params);
+
+ zassert_equal(host_command_process(&args), EC_RES_INVALID_COMMAND,
+ "Failed to fail pd_control for port %d", params.chip);
+}
+
+ZTEST_USER(host_cmd_pd_control, test_pd_reset_resume)
+{
+ /*
+ * Note: this would ideally be a host command interface check, but
+ * the only HC return which would cover this is a state string, which
+ * could be brittle.
+ */
+ zassume_true(pd_is_port_enabled(TEST_PORT), "Port not up at beginning");
+
+ host_cmd_pd_control(TEST_PORT, PD_RESET);
+
+ zassert_equal(1, board_reset_pd_mcu_fake.call_count,
+ "Failed to see board reset");
+
+ /* Give some PD task processing time */
+ k_sleep(K_SECONDS(1));
+
+ zassert_false(pd_is_port_enabled(TEST_PORT), "Port failed to suspend");
+
+ host_cmd_pd_control(TEST_PORT, PD_RESUME);
+
+ /* Give some PD task processing time */
+ k_sleep(K_SECONDS(1));
+
+ zassert_true(pd_is_port_enabled(TEST_PORT), "Port failed to resume");
+
+ RESET_FAKE(board_reset_pd_mcu);
+}
+
+ZTEST_USER(host_cmd_pd_control, test_suspend_resume)
+{
+ /*
+ * Note: this would ideally be a host command interface check, but
+ * the only HC return which would cover this is a state string, which
+ * could be brittle.
+ */
+ zassume_true(pd_is_port_enabled(TEST_PORT), "Port not up at beginning");
+
+ host_cmd_pd_control(TEST_PORT, PD_SUSPEND);
+
+ /* Give some PD task processing time */
+ k_sleep(K_SECONDS(1));
+
+ zassert_false(pd_is_port_enabled(TEST_PORT), "Port failed to suspend");
+
+ host_cmd_pd_control(TEST_PORT, PD_RESUME);
+
+ /* Give some PD task processing time */
+ k_sleep(K_SECONDS(1));
+
+ zassert_true(pd_is_port_enabled(TEST_PORT), "Port failed to resume");
+}
+
+ZTEST_USER(host_cmd_pd_control, test_control_disable)
+{
+ struct ec_params_pd_control params = { .chip = TEST_PORT,
+ .subcmd = PD_RESET };
+ struct host_cmd_handler_args args =
+ BUILD_HOST_COMMAND_PARAMS(EC_CMD_PD_CONTROL, 0, params);
+
+ host_cmd_pd_control(TEST_PORT, PD_CONTROL_DISABLE);
+
+ zassert_equal(host_command_process(&args), EC_RES_ACCESS_DENIED,
+ "Access was not denied for port %d", params.chip);
+
+ /*
+ * Disable lasts as long as the EC is booted. Use a test hook to
+ * restore our state to a normal one
+ */
+ pd_control_port_enable(TEST_PORT);
+}
+
+static void host_cmd_pd_control_begin(void *data)
+{
+ ARG_UNUSED(data);
+
+ /* Assume we have at least one USB-C port */
+ zassume_true(board_get_usb_pd_port_count() > 0,
+ "Insufficient TCPCs found");
+
+ /* Set the system into S0, since the AP would drive these commands */
+ test_set_chipset_to_s0();
+ k_sleep(K_SECONDS(1));
+}
+
+ZTEST_SUITE(host_cmd_pd_control, drivers_predicate_post_main, NULL,
+ host_cmd_pd_control_begin, NULL, NULL);
diff --git a/zephyr/test/drivers/host_cmd/src/pd_log.c b/zephyr/test/drivers/host_cmd/src/pd_log.c
new file mode 100644
index 0000000000..a6022d8bb1
--- /dev/null
+++ b/zephyr/test/drivers/host_cmd/src/pd_log.c
@@ -0,0 +1,135 @@
+/* Copyright 2022 The ChromiumOS Authors
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include <zephyr/kernel.h>
+#include <zephyr/ztest.h>
+
+#include "event_log.h"
+#include "host_command.h"
+#include "test/drivers/test_state.h"
+#include "usb_pd.h"
+
+/**
+ * @brief This is the maximum size of a single log entry.
+ *
+ * Each entry must contain some common data + up to 16 bytes of additional type
+ * specific data.
+ */
+#define MAX_EVENT_LOG_ENTRY_SIZE (sizeof(struct event_log_entry) + 16)
+
+/**
+ * @brief The size of the PD log entry data
+ *
+ * Logs from the PD include an additional 8 bytes of data to be sent to the AP.
+ */
+#define PD_LOG_ENTRY_DATA_SIZE (8)
+
+struct pd_log_fixture {
+ union {
+ uint8_t event_log_buffer[MAX_EVENT_LOG_ENTRY_SIZE];
+ struct event_log_entry log_entry;
+ };
+};
+
+static void *pd_log_setup(void)
+{
+ static struct pd_log_fixture fixture;
+
+ return &fixture;
+}
+
+static void pd_log_before(void *f)
+{
+ struct pd_log_fixture *fixture = f;
+
+ while (log_dequeue_event(&fixture->log_entry) != 0) {
+ if (fixture->log_entry.type == EVENT_LOG_NO_ENTRY) {
+ break;
+ }
+ }
+}
+
+ZTEST_SUITE(pd_log, drivers_predicate_post_main, pd_log_setup, pd_log_before,
+ NULL, NULL);
+
+ZTEST_USER(pd_log, test_bad_type)
+{
+ struct ec_params_pd_write_log_entry params = {
+ .type = PD_EVENT_ACC_BASE,
+ };
+ struct host_cmd_handler_args args = BUILD_HOST_COMMAND_PARAMS(
+ EC_CMD_PD_WRITE_LOG_ENTRY, UINT8_C(0), params);
+
+ zassert_equal(EC_RES_INVALID_PARAM, host_command_process(&args), NULL);
+}
+
+ZTEST_USER(pd_log, test_bad_port)
+{
+ struct ec_params_pd_write_log_entry params = {
+ .type = PD_EVENT_MCU_BASE,
+ };
+ struct host_cmd_handler_args args = BUILD_HOST_COMMAND_PARAMS(
+ EC_CMD_PD_WRITE_LOG_ENTRY, UINT8_C(0), params);
+
+ params.port = board_get_usb_pd_port_count() + 1;
+ zassert_equal(EC_RES_INVALID_PARAM, host_command_process(&args), NULL);
+}
+
+ZTEST_USER_F(pd_log, test_mcu_charge)
+{
+ struct ec_params_pd_write_log_entry params = {
+ .type = PD_EVENT_MCU_CHARGE,
+ .port = 0,
+ };
+ struct host_cmd_handler_args args = BUILD_HOST_COMMAND_PARAMS(
+ EC_CMD_PD_WRITE_LOG_ENTRY, UINT8_C(0), params);
+
+ zassert_ok(host_command_process(&args), NULL);
+ zassert_equal(sizeof(struct event_log_entry) + PD_LOG_ENTRY_DATA_SIZE,
+ log_dequeue_event(&fixture->log_entry), NULL);
+ zassert_equal(params.type, fixture->log_entry.type, NULL);
+ zassert_equal(PD_LOG_ENTRY_DATA_SIZE, fixture->log_entry.size, NULL);
+ zassert_equal(0, fixture->log_entry.data, NULL);
+ zassert_within(0, (int64_t)fixture->log_entry.timestamp, 10,
+ "Expected timestamp %" PRIi64
+ " to be within 10 ms of now",
+ (int64_t)fixture->log_entry.timestamp);
+}
+ZTEST_USER_F(pd_log, test_mcu_connect)
+{
+ struct ec_params_pd_write_log_entry params = {
+ .type = PD_EVENT_MCU_CONNECT,
+ .port = 0,
+ };
+ struct host_cmd_handler_args args = BUILD_HOST_COMMAND_PARAMS(
+ EC_CMD_PD_WRITE_LOG_ENTRY, UINT8_C(0), params);
+
+ zassert_ok(host_command_process(&args), NULL);
+ zassert_equal(sizeof(struct event_log_entry),
+ log_dequeue_event(&fixture->log_entry), NULL);
+ zassert_equal(params.type, fixture->log_entry.type, NULL);
+ zassert_equal(0, fixture->log_entry.size, NULL);
+ zassert_equal(0, fixture->log_entry.data, NULL);
+ zassert_within(0, (int64_t)fixture->log_entry.timestamp, 10,
+ "Expected timestamp %" PRIi64
+ " to be within 10 ms of now",
+ (int64_t)fixture->log_entry.timestamp);
+}
+
+ZTEST_USER_F(pd_log, test_read_log_entry)
+{
+ uint8_t response_buffer[sizeof(struct ec_response_pd_log) + 16];
+ struct ec_response_pd_log *response =
+ (struct ec_response_pd_log *)response_buffer;
+ struct host_cmd_handler_args args =
+ BUILD_HOST_COMMAND_SIMPLE(EC_CMD_PD_GET_LOG_ENTRY, UINT8_C(0));
+
+ args.response = response;
+ args.response_max = sizeof(response_buffer);
+
+ zassert_ok(host_command_process(&args), NULL);
+ zassert_equal(sizeof(struct event_log_entry), args.response_size, NULL);
+ zassert_equal(PD_EVENT_NO_ENTRY, response->type, NULL);
+}
diff --git a/zephyr/test/drivers/host_cmd/src/usb_pd_control.c b/zephyr/test/drivers/host_cmd/src/usb_pd_control.c
new file mode 100644
index 0000000000..c439141da9
--- /dev/null
+++ b/zephyr/test/drivers/host_cmd/src/usb_pd_control.c
@@ -0,0 +1,151 @@
+/* Copyright 2022 The ChromiumOS Authors
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include <zephyr/shell/shell.h>
+#include <zephyr/ztest.h>
+
+#include "console.h"
+#include "ec_commands.h"
+#include "emul/emul_isl923x.h"
+#include "emul/tcpc/emul_ps8xxx.h"
+#include "emul/tcpc/emul_tcpci.h"
+#include "emul/tcpc/emul_tcpci_partner_snk.h"
+#include "test/drivers/stubs.h"
+#include "test/drivers/test_state.h"
+#include "test/drivers/utils.h"
+
+#define TEST_PORT USBC_PORT_C0
+#define BAD_PORT 42
+
+struct host_cmd_usb_pd_control_fixture {
+ const struct emul *tcpci_emul;
+ const struct emul *charger_emul;
+ struct tcpci_partner_data partner;
+ struct tcpci_snk_emul_data snk_ext;
+};
+
+static enum ec_status
+run_usb_pd_control(int port, struct ec_response_usb_pd_control_v2 *resp)
+{
+ /*
+ * Note: while arguments exist to change the PD state, their use is
+ * discouraged as that causes the response to have non-deterministic
+ * results. The kernel only uses the "no change" parameters, so that is
+ * what we shall test here.
+ */
+ struct ec_params_usb_pd_control params = {
+ .port = port,
+ .role = USB_PD_CTRL_ROLE_NO_CHANGE,
+ .mux = USB_PD_CTRL_MUX_NO_CHANGE,
+ .swap = USB_PD_CTRL_SWAP_NONE
+ };
+ struct host_cmd_handler_args args =
+ BUILD_HOST_COMMAND(EC_CMD_USB_PD_CONTROL, 2, *resp, params);
+
+ return host_command_process(&args);
+}
+
+ZTEST_USER(host_cmd_usb_pd_control, test_good_index_no_partner)
+{
+ struct ec_response_usb_pd_control_v2 response;
+
+ zassert_ok(run_usb_pd_control(TEST_PORT, &response),
+ "Failed to process usb_pd_control for port %d", TEST_PORT);
+
+ /* Verify basic not-connected expectations */
+ zassert_equal(response.enabled, 0,
+ "Failed to find nothing enabled: 0x%02x",
+ response.enabled);
+ /* Don't verify role, cc, or polarity as it isn't meaningful */
+ zassert_equal(response.control_flags, 0, "Failed to see flags cleared");
+}
+
+ZTEST_USER_F(host_cmd_usb_pd_control, test_good_index_sink_partner)
+{
+ struct ec_response_usb_pd_control_v2 response;
+
+ /* Attach simple sink that shouldn't do any swaps */
+ connect_sink_to_port(&fixture->partner, fixture->tcpci_emul,
+ fixture->charger_emul);
+
+ /* Wait for connection to settle */
+ k_sleep(K_SECONDS(1));
+
+ zassert_ok(run_usb_pd_control(TEST_PORT, &response),
+ "Failed to process usb_pd_control for port %d", TEST_PORT);
+
+ /* Verify basic sink expectations */
+ zassert_equal(
+ response.enabled,
+ (PD_CTRL_RESP_ENABLED_COMMS | PD_CTRL_RESP_ENABLED_CONNECTED |
+ PD_CTRL_RESP_ENABLED_PD_CAPABLE),
+ "Failed to see full connection: 0x%02x", response.enabled);
+ /*
+ * We should be source, DFP, Vconn source, and we set our sink caps
+ * to USB comms
+ */
+ zassert_equal(response.role,
+ (PD_CTRL_RESP_ROLE_USB_COMM | PD_CTRL_RESP_ROLE_POWER |
+ PD_CTRL_RESP_ROLE_DATA | PD_CTRL_RESP_ROLE_VCONN),
+ "Failed to see expected role: 0x%02x", response.role);
+ zassert_equal(response.cc_state, PD_CC_UFP_ATTACHED,
+ "Failed to see UFP attached");
+ zassert_equal(response.control_flags, 0, "Failed to see flags cleared");
+}
+
+ZTEST_USER(host_cmd_usb_pd_control, test_bad_index)
+{
+ struct ec_response_usb_pd_control_v2 response;
+
+ zassume_true(board_get_usb_pd_port_count() < BAD_PORT,
+ "Intended bad port exists");
+ zassert_equal(run_usb_pd_control(BAD_PORT, &response),
+ EC_RES_INVALID_PARAM,
+ "Failed to fail usb_pd_control for port %d", BAD_PORT);
+}
+
+static void *host_cmd_usb_pd_control_setup(void)
+{
+ static struct host_cmd_usb_pd_control_fixture fixture;
+ struct tcpci_partner_data *partner = &fixture.partner;
+ struct tcpci_snk_emul_data *snk_ext = &fixture.snk_ext;
+
+ tcpci_partner_init(partner, PD_REV30);
+ partner->extensions = tcpci_snk_emul_init(snk_ext, partner, NULL);
+
+ /* Get references for the emulators */
+ fixture.tcpci_emul = EMUL_DT_GET(DT_NODELABEL(tcpci_emul));
+ fixture.charger_emul = EMUL_DT_GET(DT_NODELABEL(isl923x_emul));
+
+ /* Sink 5V 3A. */
+ snk_ext->pdo[0] = PDO_FIXED(5000, 3000, PDO_FIXED_COMM_CAP);
+
+ return &fixture;
+}
+
+static void host_cmd_usb_pd_control_before(void *data)
+{
+ ARG_UNUSED(data);
+
+ /* Assume we have at least one USB-C port */
+ zassume_true(board_get_usb_pd_port_count() > 0,
+ "Insufficient TCPCs found");
+
+ /* Set the system into S0, since the AP would drive these commands */
+ test_set_chipset_to_s0();
+ k_sleep(K_SECONDS(1));
+}
+
+static void host_cmd_usb_pd_control_after(void *data)
+{
+ struct host_cmd_usb_pd_control_fixture *fixture = data;
+
+ disconnect_sink_from_port(fixture->tcpci_emul);
+ k_sleep(K_SECONDS(1));
+}
+
+ZTEST_SUITE(host_cmd_usb_pd_control, drivers_predicate_post_main,
+ host_cmd_usb_pd_control_setup, host_cmd_usb_pd_control_before,
+ host_cmd_usb_pd_control_after, NULL);