summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authorGwendal Grignou <gwendal@chromium.org>2023-03-14 01:59:26 -0700
committerChromeos LUCI <chromeos-scoped@luci-project-accounts.iam.gserviceaccount.com>2023-03-23 17:23:48 +0000
commitc1f6b2a249250fc4aad2b5c5693b8111d75d8d38 (patch)
tree74f2622039b76713a6250e7fc1432a1d0655c9c1 /test
parentd693ea3d4434a1c66605beb3c9e015e20b45a701 (diff)
downloadchrome-ec-c1f6b2a249250fc4aad2b5c5693b8111d75d8d38.tar.gz
common/tablet: Allow getting out of tablet mode when sensors are broken
When sensors stop working, at least one accelerometer, the EC can not calculate the lid angle anymore. Add hook to the lid opening event, to be able to get out out of tablet mode when lid close. Move scope of the variables that keep track of the lid angle deduced from the GMR sensors. BUG=b:267680317, b:270994196 BRANCH=trogdor, dedede, many more potentially. TEST=Added unit tests. Change-Id: Iaf7cc0d27fba32b3c8616a0674a47af815921ac4 Signed-off-by: Gwendal Grignou <gwendal@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/4338479 Reviewed-by: Douglas Anderson <dianders@chromium.org> Reviewed-by: Daisuke Nojiri <dnojiri@chromium.org>
Diffstat (limited to 'test')
-rw-r--r--test/build.mk4
-rw-r--r--test/tablet_broken_sensor.c174
-rw-r--r--test/tablet_broken_sensor.tasklist10
-rw-r--r--test/tablet_no_sensor.c105
-rw-r--r--test/tablet_no_sensor.tasklist9
-rw-r--r--test/test_config.h10
6 files changed, 310 insertions, 2 deletions
diff --git a/test/build.mk b/test/build.mk
index e22563d064..923c141d33 100644
--- a/test/build.mk
+++ b/test/build.mk
@@ -102,6 +102,8 @@ test-list-host += static_if_error
test-list-host += stdlib
test-list-host += std_vector
test-list-host += system
+test-list-host += tablet_broken_sensor
+test-list-host += tablet_no_sensor
test-list-host += thermal
test-list-host += timer
test-list-host += timer_dos
@@ -262,6 +264,8 @@ stm32f_rtc-y=stm32f_rtc.o
stress-y=stress.o
system-y=system.o
system_is_locked-y=system_is_locked.o
+tablet_broken_sensor-y=tablet_broken_sensor.o
+tablet_no_sensor-y=tablet_no_sensor.o
thermal-y=thermal.o
timer_calib-y=timer_calib.o
timer_dos-y=timer_dos.o
diff --git a/test/tablet_broken_sensor.c b/test/tablet_broken_sensor.c
new file mode 100644
index 0000000000..a6577f7b80
--- /dev/null
+++ b/test/tablet_broken_sensor.c
@@ -0,0 +1,174 @@
+/* Copyright 2023 The ChromiumOS Authors
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ *
+ * Test clamshell/tablet when the sensors are broken.
+ */
+
+#include "accelgyro.h"
+#include "common.h"
+#include "console.h"
+#include "gpio.h"
+#include "hooks.h"
+#include "host_command.h"
+#include "motion_common.h"
+#include "motion_sense.h"
+#include "tablet_mode.h"
+#include "test_util.h"
+#include "timer.h"
+#include "util.h"
+
+/*****************************************************************************/
+/* Mock functions */
+static int accel_init(struct motion_sensor_t *s)
+{
+ return EC_ERROR_UNKNOWN;
+}
+
+/* Only populate _init(), sensor stack should not touch the sensors on failure.
+ */
+const struct accelgyro_drv test_motion_sense = {
+ .init = accel_init,
+};
+
+struct motion_sensor_t motion_sensors[] = {
+ [BASE] = {
+ .name = "base",
+ .active_mask = SENSOR_ACTIVE_S0_S3_S5,
+ .chip = MOTIONSENSE_CHIP_LSM6DS0,
+ .type = MOTIONSENSE_TYPE_ACCEL,
+ .location = MOTIONSENSE_LOC_BASE,
+ .drv = &test_motion_sense,
+ .rot_standard_ref = NULL,
+ .default_range = 2,
+ },
+ [LID] = {
+ .name = "lid",
+ .active_mask = SENSOR_ACTIVE_S0_S3_S5,
+ .chip = MOTIONSENSE_CHIP_KXCJ9,
+ .type = MOTIONSENSE_TYPE_ACCEL,
+ .location = MOTIONSENSE_LOC_LID,
+ .drv = &test_motion_sense,
+ .rot_standard_ref = NULL,
+ .default_range = 2,
+ },
+};
+const unsigned int motion_sensor_count = ARRAY_SIZE(motion_sensors);
+
+static int tablet_hook_count;
+
+static void tablet_mode_change_hook(void)
+{
+ tablet_hook_count++;
+}
+DECLARE_HOOK(HOOK_TABLET_MODE_CHANGE, tablet_mode_change_hook,
+ HOOK_PRIO_DEFAULT);
+
+void before_test(void)
+{
+ /* Make sure the device lid is in a consistent state (close). */
+ gpio_set_level(GPIO_TABLET_MODE_L, 1);
+ msleep(50);
+ gpio_set_level(GPIO_LID_OPEN, 0);
+ msleep(50);
+ tablet_hook_count = 1;
+}
+
+/*
+ * The device is in clamshell mode from before_test(),
+ * Go through GPIO transitions and observe the table mode state.
+ */
+test_static int test_start_lid_close(void)
+{
+ TEST_ASSERT(!tablet_get_mode());
+
+ /* Opening, No change. */
+ gpio_set_level(GPIO_LID_OPEN, 1);
+ msleep(50);
+ TEST_ASSERT(tablet_hook_count == 1);
+ TEST_ASSERT(!tablet_get_mode());
+
+ /* full 360, tablet mode. */
+ gpio_set_level(GPIO_TABLET_MODE_L, 0);
+ msleep(50);
+ TEST_ASSERT(tablet_hook_count == 2);
+ TEST_ASSERT(tablet_get_mode());
+
+ /* Going out of 360 mode, no change. */
+ gpio_set_level(GPIO_TABLET_MODE_L, 1);
+ msleep(50);
+ TEST_ASSERT(tablet_hook_count == 2);
+ TEST_ASSERT(tablet_get_mode());
+
+ /* Back to close. */
+ gpio_set_level(GPIO_LID_OPEN, 0);
+ msleep(50);
+ TEST_ASSERT(tablet_hook_count == 3);
+ TEST_ASSERT(!tablet_get_mode());
+
+ return EC_SUCCESS;
+}
+
+/*
+ * Put the device in tablet mode first.
+ * Reset the EC, keep the existing GPIO level.
+ * Verify the state is not forgotten when the EC starts in tablet mode after
+ * reset.
+ */
+test_static int test_start_tablet_mode(void)
+{
+ /* Go in tablet mode */
+ gpio_set_level(GPIO_LID_OPEN, 1);
+ gpio_set_level(GPIO_TABLET_MODE_L, 0);
+ msleep(50);
+ TEST_ASSERT(tablet_hook_count == 2);
+
+ /* Shutdown device */
+ hook_notify(HOOK_CHIPSET_SHUTDOWN);
+
+ msleep(50);
+ TEST_ASSERT(sensor_active == SENSOR_ACTIVE_S5);
+ TEST_ASSERT(tablet_hook_count == 2);
+ TEST_ASSERT(tablet_get_mode());
+
+ return EC_SUCCESS;
+}
+
+/*
+ * Put the device in tablet mode first.
+ * Do a fast transition from 0 degree to 360 degree:
+ * Observe the transition happens.
+ * then 360 degree to 0 degree.
+ * Observe the transition happens.
+ */
+test_static int test_fast_transition(void)
+{
+ TEST_ASSERT(!tablet_get_mode());
+
+ /* Go in tablet mode fast.*/
+ gpio_set_level(GPIO_LID_OPEN, 1);
+ gpio_set_level(GPIO_TABLET_MODE_L, 0);
+ msleep(50);
+ TEST_ASSERT(tablet_get_mode());
+ TEST_ASSERT(tablet_hook_count == 2);
+
+ /* Go in clamshell mode fast.*/
+ gpio_set_level(GPIO_LID_OPEN, 0);
+ gpio_set_level(GPIO_TABLET_MODE_L, 1);
+ msleep(50);
+ TEST_ASSERT(!tablet_get_mode());
+ TEST_ASSERT(tablet_hook_count == 3);
+
+ return EC_SUCCESS;
+}
+
+void run_test(int argc, const char **argv)
+{
+ test_reset();
+
+ RUN_TEST(test_start_lid_close);
+ RUN_TEST(test_start_tablet_mode);
+ RUN_TEST(test_fast_transition);
+
+ test_print_result();
+}
diff --git a/test/tablet_broken_sensor.tasklist b/test/tablet_broken_sensor.tasklist
new file mode 100644
index 0000000000..04f8e3006d
--- /dev/null
+++ b/test/tablet_broken_sensor.tasklist
@@ -0,0 +1,10 @@
+/* Copyright 2013 The ChromiumOS Authors
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+/**
+ * See CONFIG_TASK_LIST in config.h for details.
+ */
+#define CONFIG_TEST_TASK_LIST \
+ TASK_TEST(MOTIONSENSE, motion_sense_task, NULL, TASK_STACK_SIZE)
diff --git a/test/tablet_no_sensor.c b/test/tablet_no_sensor.c
new file mode 100644
index 0000000000..f6a3d16c11
--- /dev/null
+++ b/test/tablet_no_sensor.c
@@ -0,0 +1,105 @@
+/* Copyright 2023 The ChromiumOS Authors
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ *
+ * Test clamshell/tablet when Only the GMR sensor is driving the tablet mode:
+ * In that mode, tablet mode is entered only when the lid angle is 360 degree.
+ */
+
+#include "common.h"
+#include "console.h"
+#include "gpio.h"
+#include "hooks.h"
+#include "host_command.h"
+#include "tablet_mode.h"
+#include "test_util.h"
+#include "timer.h"
+#include "util.h"
+
+static int tablet_hook_count;
+
+static void tablet_mode_change_hook(void)
+{
+ tablet_hook_count++;
+}
+DECLARE_HOOK(HOOK_TABLET_MODE_CHANGE, tablet_mode_change_hook,
+ HOOK_PRIO_DEFAULT);
+
+void before_test(void)
+{
+ /* Make sure the device lid is in a consistent state (close). */
+ gpio_set_level(GPIO_TABLET_MODE_L, 1);
+ msleep(50);
+ gpio_set_level(GPIO_LID_OPEN, 0);
+ msleep(50);
+ tablet_hook_count = 1;
+}
+
+/*
+ * The device is in clamshell mode from before_test,
+ * Go through GPIO transitions and observe the table mode state.
+ */
+test_static int test_start_lid_close(void)
+{
+ TEST_ASSERT(!tablet_get_mode());
+
+ /* Opening, No change. */
+ gpio_set_level(GPIO_LID_OPEN, 1);
+ msleep(50);
+ TEST_ASSERT(tablet_hook_count == 1);
+ TEST_ASSERT(!tablet_get_mode());
+
+ /* full 360, tablet mode. */
+ gpio_set_level(GPIO_TABLET_MODE_L, 0);
+ msleep(50);
+ TEST_ASSERT(tablet_hook_count == 2);
+ TEST_ASSERT(tablet_get_mode());
+
+ /* Get out of full 360 mode, Immediately back to clamshell mode. */
+ gpio_set_level(GPIO_TABLET_MODE_L, 1);
+ msleep(50);
+ TEST_ASSERT(tablet_hook_count == 3);
+ TEST_ASSERT(!tablet_get_mode());
+
+ /* Back to close, no change. */
+ gpio_set_level(GPIO_LID_OPEN, 0);
+ msleep(50);
+ TEST_ASSERT(tablet_hook_count == 3);
+ TEST_ASSERT(!tablet_get_mode());
+
+ return EC_SUCCESS;
+}
+
+/*
+ * Put the device in tablet mode first.
+ * Reset the EC, keep the existing GPIO level.
+ * Verify the state is not forgotten when the EC starts in tablet mode after
+ * reset.
+ */
+test_static int test_start_tablet_mode(void)
+{
+ /* Go in tablet mode */
+ gpio_set_level(GPIO_LID_OPEN, 1);
+ gpio_set_level(GPIO_TABLET_MODE_L, 0);
+ msleep(50);
+ TEST_ASSERT(tablet_hook_count == 2);
+
+ /* Shutdown device */
+ hook_notify(HOOK_CHIPSET_SHUTDOWN);
+
+ /* Check we start in tablet mode */
+ msleep(50);
+ TEST_ASSERT(tablet_get_mode());
+
+ return EC_SUCCESS;
+}
+
+void run_test(int argc, const char **argv)
+{
+ test_reset();
+
+ RUN_TEST(test_start_lid_close);
+ RUN_TEST(test_start_tablet_mode);
+
+ test_print_result();
+}
diff --git a/test/tablet_no_sensor.tasklist b/test/tablet_no_sensor.tasklist
new file mode 100644
index 0000000000..47a61cc5a5
--- /dev/null
+++ b/test/tablet_no_sensor.tasklist
@@ -0,0 +1,9 @@
+/* Copyright 2013 The ChromiumOS Authors
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+/**
+ * See CONFIG_TASK_LIST in config.h for details.
+ */
+#define CONFIG_TEST_TASK_LIST
diff --git a/test/test_config.h b/test/test_config.h
index 926ebba090..d683627c8a 100644
--- a/test/test_config.h
+++ b/test/test_config.h
@@ -199,7 +199,8 @@
#if defined(CONFIG_ONLINE_CALIB) || defined(TEST_BODY_DETECTION) || \
defined(TEST_MOTION_ANGLE) || defined(TEST_MOTION_ANGLE_TABLET) || \
- defined(TEST_MOTION_LID) || defined(TEST_MOTION_SENSE_FIFO)
+ defined(TEST_MOTION_LID) || defined(TEST_MOTION_SENSE_FIFO) || \
+ defined(TEST_TABLET_BROKEN_SENSOR)
enum sensor_id {
BASE,
LID,
@@ -207,7 +208,7 @@ enum sensor_id {
};
#if defined(TEST_MOTION_ANGLE) || defined(TEST_MOTION_ANGLE_TABLET) || \
- defined(TEST_MOTION_LID)
+ defined(TEST_MOTION_LID) || defined(TEST_TABLET_BROKEN_SENSOR)
#define CONFIG_LID_ANGLE
#define CONFIG_LID_ANGLE_SENSOR_BASE BASE
#define CONFIG_LID_ANGLE_SENSOR_LID LID
@@ -231,6 +232,11 @@ enum sensor_id {
(1 << CONFIG_LID_ANGLE_SENSOR_LID))
#endif
+#if defined(TEST_TABLET_BROKEN_SENSOR) || defined(TEST_TABLET_NO_SENSOR)
+#define CONFIG_TABLET_MODE
+#define CONFIG_GMR_TABLET_MODE
+#endif
+
#if defined(TEST_BODY_DETECTION)
#define CONFIG_BODY_DETECTION
#define CONFIG_BODY_DETECTION_SENSOR BASE