blob: a6577f7b80f3b5382b1f088b3d3decc2143751b8 [file] [log] [blame]
/* 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();
}