Add a test of checking power button handling

This test checks power button is correctly debounced, and also check
power button press of different length are handled correctly.

BUG=chrome-os-partner:10273
TEST=Test passed

Change-Id: I18595c60896255d36326731d28bab55e64c6bca2
Reviewed-on: https://gerrit.chromium.org/gerrit/25505
Reviewed-by: Vincent Palatin <vpalatin@chromium.org>
Reviewed-by: Randall Spangler <rspangler@chromium.org>
Tested-by: Vic Yang <victoryang@chromium.org>
Commit-Ready: Vic Yang <victoryang@chromium.org>
This commit is contained in:
Vic Yang
2012-06-17 15:51:00 +08:00
committed by Gerrit
parent 7ae80c0552
commit 7eabcb4e69
7 changed files with 436 additions and 0 deletions

117
chip/lm4/mock_gpio.c Normal file
View File

@@ -0,0 +1,117 @@
/* Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
/* Mock GPIO module for Chrome EC */
#include "board.h"
#include "console.h"
#include "gpio.h"
#include "util.h"
static int8_t mock_value[GPIO_COUNT] = {0};
static int8_t mock_gpio_im[GPIO_COUNT] = {0};
int gpio_pre_init(void)
{
/* Nothing to do */
return EC_SUCCESS;
}
void gpio_set_alternate_function(int port, int mask, int func)
{
/* Not implemented */
return;
}
const char *gpio_get_name(enum gpio_signal signal)
{
return gpio_list[signal].name;
}
int gpio_get_level(enum gpio_signal signal)
{
return mock_value[signal] ? 1 : 0;
}
int gpio_set_level(enum gpio_signal signal, int value)
{
mock_value[signal] = value;
return EC_SUCCESS;
}
int gpio_set_flags(enum gpio_signal signal, int flags)
{
/* Not implemented */
return EC_SUCCESS;
}
int gpio_enable_interrupt(enum gpio_signal signal)
{
const struct gpio_info *g = gpio_list + signal;
/* Fail if no interrupt handler */
if (!g->irq_handler)
return EC_ERROR_UNKNOWN;
mock_gpio_im[signal] = 1;
return EC_SUCCESS;
}
/* Find a GPIO signal by name. Returns the signal index, or GPIO_COUNT if
* no match. */
static enum gpio_signal find_signal_by_name(const char *name)
{
const struct gpio_info *g = gpio_list;
int i;
if (!name || !*name)
return GPIO_COUNT;
for (i = 0; i < GPIO_COUNT; i++, g++) {
if (!strcasecmp(name, g->name))
return i;
}
return GPIO_COUNT;
}
static int command_gpio_mock(int argc, char **argv)
{
char *e;
int v, i;
const struct gpio_info *g;
if (argc < 3)
return EC_ERROR_PARAM_COUNT;
i = find_signal_by_name(argv[1]);
if (i == GPIO_COUNT)
return EC_ERROR_PARAM1;
g = gpio_list + i;
v = strtoi(argv[2], &e, 0);
if (*e)
return EC_ERROR_PARAM2;
gpio_set_level(i, v);
if (g->irq_handler && mock_gpio_im[i])
g->irq_handler(i);
return EC_SUCCESS;
}
DECLARE_CONSOLE_COMMAND(gpiomock, command_gpio_mock,
"name <0 | 1>",
"Mock a GPIO input",
NULL);

View File

@@ -47,6 +47,13 @@ int pwm_get_keyboard_backlight_enabled(void)
}
int pwm_enable_keyboard_backlight(int enable)
{
/* Not implemented */
return EC_SUCCESS;
}
void pwm_task(void)
{
/* Do nothing */

58
common/mock_i8042.c Normal file
View File

@@ -0,0 +1,58 @@
/* Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*
* Mock EC i8042 interface code.
*/
#include "i8042.h"
#include "timer.h"
#include "uart.h"
void i8042_receives_data(int data)
{
/* Not implemented */
return;
}
void i8042_receives_command(int cmd)
{
/* Not implemented */
return;
}
void i8042_command_task(void)
{
/* Do nothing */
while (1)
usleep(5000000);
}
enum ec_error_list i8042_send_to_host(int len, const uint8_t *bytes)
{
uart_printf("i8042 SEND\n");
return EC_SUCCESS;
}
void i8042_enable_keyboard_irq(void) {
/* Not implemented */
return;
}
void i8042_disable_keyboard_irq(void) {
/* Not implemented */
return;
}
void i8042_flush_buffer()
{
/* Not implemented */
return;
}

View File

@@ -6,11 +6,15 @@
/* Mock X86 chipset power control module for Chrome EC */
#include "chipset.h"
#include "console.h"
#include "lpc.h"
#include "timer.h"
#include "uart.h"
#include "util.h"
#include "x86_power.h"
static int mock_power_on = 0;
void x86_power_cpu_overheated(int too_hot)
{
/* Print transitions */
@@ -31,6 +35,12 @@ void x86_power_force_shutdown(void)
}
void x86_power_reset(int cold_reset)
{
uart_printf("X86 Power %s reset\n", cold_reset ? "cold" : "warm");
}
void chipset_throttle_cpu(int throttle)
{
/* Print transitions */
@@ -45,6 +55,23 @@ void chipset_throttle_cpu(int throttle)
}
void chipset_exit_hard_off(void)
{
/* Not implemented */
return;
}
int chipset_in_state(int state_mask)
{
if (mock_power_on)
return state_mask == CHIPSET_STATE_ON;
else
return (state_mask == CHIPSET_STATE_SOFT_OFF) ||
(state_mask == CHIPSET_STATE_ANY_OFF);
}
void x86_power_interrupt(enum gpio_signal signal)
{
/* Not implemented */
@@ -58,3 +85,25 @@ void x86_power_task(void)
while (1)
usleep(5000000);
}
static int command_mock_power(int argc, char **argv)
{
if (argc != 2)
return EC_ERROR_PARAM_COUNT;
if (!strcasecmp(argv[1], "on")) {
mock_power_on = 1;
}
else if (!strcasecmp(argv[1], "off")) {
mock_power_on = 0;
}
else
return EC_ERROR_PARAM1;
return EC_SUCCESS;
}
DECLARE_CONSOLE_COMMAND(powermock, command_mock_power,
"<on | off>",
"Mock power state",
NULL);

View File

@@ -7,6 +7,7 @@
#
test-list=hello pingpong timer_calib timer_dos timer_jump mutex thermal
test-list+=power_button
#disable: powerdemo
pingpong-y=pingpong.o
@@ -20,3 +21,9 @@ chip-mock-thermal-lpc.o=mock_lpc.o
chip-mock-thermal-pwm.o=mock_pwm.o
common-mock-thermal-x86_power.o=mock_x86_power.o
common-mock-thermal-temp_sensor.o=mock_temp_sensor.o
# Mock modules for 'power_button'
chip-mock-power_button-gpio.o=mock_gpio.o
chip-mock-power_button-pwm.o=mock_pwm.o
common-mock-power_button-x86_power.o=mock_x86_power.o
common-mock-power_button-i8042.o=mock_i8042.o

174
test/power_button.py Normal file
View File

@@ -0,0 +1,174 @@
# Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
#
# Power button debounce test
#
# Refer to section 1.3 Power Button of
# https://sites.google.com/a/google.com/chromeos-partners/pages/
# tech-docs/firmware/ec-specification-v119
#
import time
SHORTER_THAN_T0 = 0.01
LONGER_THAN_T0 = 0.05
LONGER_THAN_T1 = 5
def check_no_output(helper, reg_ex):
success = False
try:
helper.wait_output(reg_ex, use_re=True, timeout=1)
except:
success = True
return success
def consume_output(helper, reg_ex):
done = False
while not done:
try:
helper.wait_output(reg_ex, use_re=True, timeout=1)
except:
done = True
def test(helper):
helper.wait_output("--- UART initialized")
# Release power button, set to soft off, and enable keyboard
helper.ec_command("gpiomock POWER_BUTTONn 1")
helper.ec_command("powermock off")
helper.ec_command("kbd enable")
consume_output(helper, "PB released")
helper.trace("Press power button for shorter than T0 and check this\n" +
"event is ignored\n")
helper.ec_command("gpiomock POWER_BUTTONn 0")
time.sleep(SHORTER_THAN_T0)
helper.ec_command("gpiomock POWER_BUTTONn 1")
if not check_no_output(helper, "PB released"):
return False
helper.trace("Press power button for longer than T0 and check this\n" +
"event is treated as a single press.")
helper.ec_command("gpiomock POWER_BUTTONn 0")
time.sleep(LONGER_THAN_T0)
helper.ec_command("gpiomock POWER_BUTTONn 1")
helper.wait_output("PB released", timeout=1)
# Expect shown only once
if not check_no_output(helper, "PB released"):
return False
helper.trace("Press power button for two consecutive SHORTER_THAN_T0\n" +
"period and check this event is ignored\n")
helper.ec_command("gpiomock POWER_BUTTONn 0")
time.sleep(SHORTER_THAN_T0)
helper.ec_command("gpiomock POWER_BUTTONn 1")
time.sleep(SHORTER_THAN_T0)
helper.ec_command("gpiomock POWER_BUTTONn 0")
time.sleep(SHORTER_THAN_T0)
helper.ec_command("gpiomock POWER_BUTTONn 1")
if not check_no_output(helper, "PB released"):
return False
helper.trace("Hold down power button for LONGER_THAN_T0 and check a\n" +
"single press is sent out\n")
consume_output(helper, "pwrbtn=")
helper.ec_command("gpiomock POWER_BUTTONn 0")
time.sleep(LONGER_THAN_T0)
helper.ec_command("gpiomock POWER_BUTTONn 1")
helper.wait_output("pwrbtn=LOW", timeout=1)
helper.wait_output("pwrbtn=HIGH", timeout=1)
if not check_no_output(helper, "pwrbtn=LOW"):
return False
helper.trace("Press power button for SHORTER_THAN_T0, release for\n" +
"SHORTER_THAN_T0, and then press for LONGER_THAN_T0.\n" +
"Check this is treated as a single press\n")
helper.ec_command("gpiomock POWER_BUTTONn 0")
time.sleep(SHORTER_THAN_T0)
helper.ec_command("gpiomock POWER_BUTTONn 1")
time.sleep(SHORTER_THAN_T0)
helper.ec_command("gpiomock POWER_BUTTONn 0")
time.sleep(LONGER_THAN_T0)
helper.ec_command("gpiomock POWER_BUTTONn 1")
helper.wait_output("pwrbtn=LOW", timeout=1)
helper.wait_output("pwrbtn=HIGH", timeout=1)
if not check_no_output(helper, "pwrbtn=LOW"):
return False
helper.trace("Hold down power button, wait for power button press\n" +
"sent out. Then relase for SHORTER_THAN_T0, check power\n" +
"button release is not sent out. Expect power button is\n" +
"treated as hold (ignoring the relase bounce)\n")
helper.ec_command("gpiomock POWER_BUTTONn 0")
helper.wait_output("pwrbtn=LOW", timeout=1)
helper.ec_command("gpiomock POWER_BUTTONn 1")
time.sleep(SHORTER_THAN_T0)
helper.ec_command("gpiomock POWER_BUTTONn 0")
if not check_no_output(helper, "PB released"):
return False
helper.ec_command("gpiomock POWER_BUTTONn 1")
helper.wait_output("PB released", timeout=1)
helper.trace("When system is off, hold down power button for\n" +
"LONGER_THAN_T0. Check the initial is stretched\n")
consume_output(helper, "pwrbtn=")
helper.ec_command("gpiomock POWER_BUTTONn 0")
time.sleep(LONGER_THAN_T0)
helper.ec_command("gpiomock POWER_BUTTONn 1")
t_low = helper.wait_output("\[(?P<t>[\d\.]+) PB PCH pwrbtn=LOW\]",
use_re=True)["t"]
t_high = helper.wait_output("\[(?P<t>[\d\.]+) PB PCH pwrbtn=HIGH\]",
use_re=True)["t"]
if not check_no_output(helper, "pwrbtn=LOW"):
return False
if float(t_high) - float(t_low) <= LONGER_THAN_T0 - 0.1:
return False
helper.trace("When system is off, hold down power button for\n" +
"LONGER_THAN_T0. Check no scan code is send\n")
consume_output(helper, "i8042 SEND")
helper.ec_command("gpiomock POWER_BUTTONn 0")
time.sleep(LONGER_THAN_T0)
helper.ec_command("gpiomock POWER_BUTTONn 1")
if not check_no_output(helper, "i8042 SEND"):
return False
helper.trace("While powered on, hold down power button for\n" +
"LONGER_THAN_T0. A single short pulse should be sent\n")
consume_output(helper, "pwrbtn=")
helper.ec_command("powermock on")
helper.ec_command("gpiomock POWER_BUTTONn 0")
time.sleep(LONGER_THAN_T0)
helper.ec_command("gpiomock POWER_BUTTONn 1")
t_low = helper.wait_output("\[(?P<t>[\d\.]+) PB PCH pwrbtn=LOW\]",
use_re=True)["t"]
t_high = helper.wait_output("\[(?P<t>[\d\.]+) PB PCH pwrbtn=HIGH\]",
use_re=True)["t"]
if not check_no_output(helper, "pwrbtn=LOW"):
return False
if float(t_high) - float(t_low) >= 0.1:
return False
helper.trace("While powered on, hold down power button for\n" +
"LONGER_THAN_T0. Scan code should be sent\n")
consume_output(helper, "i8042 SEND")
helper.ec_command("gpiomock POWER_BUTTONn 0")
helper.wait_output("i8042 SEND", timeout=1) # Expect make code
time.sleep(LONGER_THAN_T0)
helper.ec_command("gpiomock POWER_BUTTONn 1")
helper.wait_output("i8042 SEND", timeout=1) # Expect release code
helper.trace("While powered on, hold down power button for\n" +
"LONGER_THAN_T1 and check two presses are sent out\n")
consume_output(helper, "pwrbtn=")
helper.ec_command("gpiomock POWER_BUTTONn 0")
time.sleep(LONGER_THAN_T1)
helper.ec_command("gpiomock POWER_BUTTONn 1")
helper.wait_output("pwrbtn=LOW", timeout=1)
helper.wait_output("pwrbtn=HIGH", timeout=1)
helper.wait_output("pwrbtn=LOW", timeout=1)
helper.wait_output("pwrbtn=HIGH", timeout=1)
if not check_no_output(helper, "pwrbtn=LOW"):
return False
return True # PASS !

View File

@@ -0,0 +1,24 @@
/* Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
/**
* List of enabled tasks in the priority order
*
* The first one has the lowest priority.
*
* For each task, use the macro TASK(n, r, d) where :
* 'n' in the name of the task
* 'r' in the main routine of the task
* 'd' in an opaque parameter passed to the routine at startup
*/
#define CONFIG_TASK_LIST \
TASK(WATCHDOG, watchdog_task, NULL) \
TASK(PWM, pwm_task, NULL) \
TASK(TYPEMATIC, keyboard_typematic_task, NULL) \
TASK(X86POWER, x86_power_task, NULL) \
TASK(I8042CMD, i8042_command_task, NULL) \
TASK(POWERBTN, power_button_task, NULL) \
TASK(KEYSCAN, keyboard_scan_task, NULL) \
TASK(CONSOLE, console_task, NULL)