summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--common/tablet_mode.c41
-rw-r--r--zephyr/test/drivers/host_cmd/CMakeLists.txt1
-rw-r--r--zephyr/test/drivers/host_cmd/src/tablet_mode.c111
3 files changed, 151 insertions, 2 deletions
diff --git a/common/tablet_mode.c b/common/tablet_mode.c
index 576e80c0ef..1a86997eb4 100644
--- a/common/tablet_mode.c
+++ b/common/tablet_mode.c
@@ -28,6 +28,12 @@ static uint32_t tablet_mode;
*/
static bool tablet_mode_forced;
+/*
+ * Console command can force the value of tablet_mode. If tablet_mode_force is
+ * false, use stored tablet mode value before it was (possibly) overridden.
+ */
+static uint32_t tablet_mode_store;
+
/* True if GMR sensor is reporting 360 degrees. */
static bool gmr_sensor_at_360;
@@ -173,11 +179,42 @@ void gmr_tablet_switch_disable(void)
}
#endif
+static enum ec_status tablet_mode_command(struct host_cmd_handler_args *args)
+{
+ const struct ec_params_set_tablet_mode *p = args->params;
+
+ if (tablet_mode_forced == false)
+ tablet_mode_store = tablet_mode;
+
+ switch (p->tablet_mode) {
+ case TABLET_MODE_DEFAULT:
+ tablet_mode = tablet_mode_store;
+ tablet_mode_forced = false;
+ break;
+ case TABLET_MODE_FORCE_TABLET:
+ tablet_mode = TABLET_TRIGGER_LID;
+ tablet_mode_forced = true;
+ break;
+ case TABLET_MODE_FORCE_CLAMSHELL:
+ tablet_mode = 0;
+ tablet_mode_forced = true;
+ break;
+ default:
+ CPRINTS("Invalid EC_CMD_SET_TABLET_MODE parameter: %d",
+ p->tablet_mode);
+ return EC_RES_INVALID_PARAM;
+ }
+
+ notify_tablet_mode_change();
+
+ return EC_RES_SUCCESS;
+}
+DECLARE_HOST_COMMAND(EC_CMD_SET_TABLET_MODE, tablet_mode_command,
+ EC_VER_MASK(0) | EC_VER_MASK(1));
+
#ifdef CONFIG_TABLET_MODE
static int command_settabletmode(int argc, const char **argv)
{
- static uint32_t tablet_mode_store;
-
if (argc == 1) {
print_tablet_mode();
return EC_SUCCESS;
diff --git a/zephyr/test/drivers/host_cmd/CMakeLists.txt b/zephyr/test/drivers/host_cmd/CMakeLists.txt
index 286685089b..0bd6ac613a 100644
--- a/zephyr/test/drivers/host_cmd/CMakeLists.txt
+++ b/zephyr/test/drivers/host_cmd/CMakeLists.txt
@@ -14,6 +14,7 @@ target_sources(app PRIVATE
src/pd_control.c
src/pd_chip_info.c
src/pd_log.c
+ src/tablet_mode.c
src/usb_pd_control.c
src/usb_pd_host_cmd.c
)
diff --git a/zephyr/test/drivers/host_cmd/src/tablet_mode.c b/zephyr/test/drivers/host_cmd/src/tablet_mode.c
new file mode 100644
index 0000000000..cb65899c4f
--- /dev/null
+++ b/zephyr/test/drivers/host_cmd/src/tablet_mode.c
@@ -0,0 +1,111 @@
+/* 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 "hooks.h"
+#include "host_command.h"
+#include "tablet_mode.h"
+#include "emul/emul_common_i2c.h"
+#include "emul/emul_smart_battery.h"
+#include "test/drivers/test_state.h"
+#include "test/drivers/utils.h"
+
+struct host_cmd_tablet_mode_fixture {
+ const struct emul *emul;
+ struct i2c_common_emul_data *i2c_emul;
+};
+
+static void host_cmd_tablet_mode_before(void *f)
+{
+ ARG_UNUSED(f);
+ tablet_reset();
+}
+
+static void host_cmd_tablet_mode_after(void *f)
+{
+ ARG_UNUSED(f);
+ tablet_reset();
+}
+
+ZTEST_SUITE(host_cmd_tablet_mode, drivers_predicate_post_main, NULL,
+ host_cmd_tablet_mode_before, host_cmd_tablet_mode_after, NULL);
+
+/* Test tablet mode can be enabled with a host command. */
+ZTEST_USER_F(host_cmd_tablet_mode, test_tablet_mode_on)
+{
+ int rv;
+ struct ec_params_set_tablet_mode params = {
+ .tablet_mode = TABLET_MODE_FORCE_TABLET
+ };
+
+ struct host_cmd_handler_args args = BUILD_HOST_COMMAND_PARAMS(
+ EC_CMD_SET_TABLET_MODE, UINT8_C(0), params);
+
+ rv = host_command_process(&args);
+ zassert_equal(EC_RES_SUCCESS, rv, "Expected EC_RES_SUCCESS, but got %d",
+ rv);
+ /* Return 1 if in tablet mode, 0 otherwise */
+ rv = tablet_get_mode();
+ zassert_equal(rv, 1, "unexpected tablet mode: %d", rv);
+}
+
+/* Test tablet mode can be disabled with a host command. */
+ZTEST_USER_F(host_cmd_tablet_mode, test_tablet_mode_off)
+{
+ int rv;
+ struct ec_params_set_tablet_mode params = {
+ .tablet_mode = TABLET_MODE_FORCE_CLAMSHELL
+ };
+
+ struct host_cmd_handler_args args = BUILD_HOST_COMMAND_PARAMS(
+ EC_CMD_SET_TABLET_MODE, UINT8_C(0), params);
+
+ rv = host_command_process(&args);
+ zassert_equal(EC_RES_SUCCESS, rv, "Expected EC_RES_SUCCESS, but got %d",
+ rv);
+ /* Return 1 if in tablet mode, 0 otherwise */
+ rv = tablet_get_mode();
+ zassert_equal(rv, 0, "unexpected tablet mode: %d", rv);
+}
+
+/* Test tablet mode can be reset with a host command. */
+ZTEST_USER_F(host_cmd_tablet_mode, test_tablet_mode_reset)
+{
+ int rv;
+ struct ec_params_set_tablet_mode params = {
+ .tablet_mode = TABLET_MODE_DEFAULT
+ };
+
+ struct host_cmd_handler_args args = BUILD_HOST_COMMAND_PARAMS(
+ EC_CMD_SET_TABLET_MODE, UINT8_C(0), params);
+
+ rv = host_command_process(&args);
+ zassert_equal(EC_RES_SUCCESS, rv, "Expected EC_RES_SUCCESS, but got %d",
+ rv);
+ /* Return 1 if in tablet mode, 0 otherwise */
+ rv = tablet_get_mode();
+ zassert_equal(rv, 0, "unexpected tablet mode: %d", rv);
+}
+
+/* Test tablet mode can handle invalid host command parameters. */
+ZTEST_USER_F(host_cmd_tablet_mode, test_tablet_mode_invalid_parameter)
+{
+ int rv;
+ struct ec_params_set_tablet_mode params = {
+ .tablet_mode = 0xEE /* Sufficiently random, bad value.*/
+ };
+
+ struct host_cmd_handler_args args = BUILD_HOST_COMMAND_PARAMS(
+ EC_CMD_SET_TABLET_MODE, UINT8_C(0), params);
+
+ rv = host_command_process(&args);
+ zassert_equal(EC_RES_INVALID_PARAM, rv,
+ "Expected EC_RES_INVALID_PARAM, but got %d", rv);
+ /* Return 1 if in tablet mode, 0 otherwise */
+ rv = tablet_get_mode();
+ zassert_equal(rv, 0, "unexpected tablet mode: %d", rv);
+}