summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpandeyan <anshuman.pandey@intel.com>2020-01-31 12:03:17 +0530
committerCommit Bot <commit-bot@chromium.org>2020-03-17 10:59:27 +0000
commite5e676f641dec32ddf4b32d1b8f4f9636e31ff2a (patch)
tree70ff7dda81a04ab75e1f402847230d302343050c
parentc0bc2333b28bfad368768292fa84808bfb9cf954 (diff)
downloadchrome-ec-e5e676f641dec32ddf4b32d1b8f4f9636e31ff2a.tar.gz
Button: add ectool command to simulate button press
Added a new ectool command 'ectool button' for simulating volume up and volume down button operations along with the duration in milli-seconds for which button needs to be pressed. BUG=b:149659987 BRANCH=None TEST=Tested on hatch board. From Kernel console, entered the below commands: $ectool button vup 500 Observed volume UP key press on EC console. Change-Id: I6fcdf80ea45b80403f72af89ce99214226731d0f Signed-off-by: pandeyan <anshuman.pandey@intel.com> Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/2059929 Reviewed-by: Jett Rink <jettrink@chromium.org>
-rw-r--r--common/button.c133
-rw-r--r--include/button.h18
-rw-r--r--include/config.h8
-rw-r--r--include/ec_commands.h37
-rw-r--r--util/ectool.c55
5 files changed, 188 insertions, 63 deletions
diff --git a/common/button.c b/common/button.c
index 8cbdd50e5a..b800302d32 100644
--- a/common/button.c
+++ b/common/button.c
@@ -5,6 +5,7 @@
/* Button module for Chrome EC */
+#include "atomic.h"
#include "button.h"
#include "chipset.h"
#include "common.h"
@@ -33,8 +34,15 @@ static struct button_state_t __bss_slow state[BUTTON_COUNT];
static uint64_t __bss_slow next_deferred_time;
-#ifdef CONFIG_CMD_BUTTON
-static int siml_btn_presd;
+#if defined(CONFIG_CMD_BUTTON) || defined(CONFIG_HOSTCMD_BUTTON)
+#define CONFIG_SIMULATED_BUTTON
+#endif
+
+#ifdef CONFIG_SIMULATED_BUTTON
+/* Bitmask to keep track of simulated state of each button.
+ * Bit numbers are aligned to enum button.
+ */
+static int sim_button_state;
/*
* Flip state of associated button type in sim_button_state bitmask.
@@ -53,18 +61,7 @@ static int siml_btn_presd;
*/
static int simulated_button_pressed(const struct button_config *button)
{
- /* bitmask to keep track of simulated state of each button */
- static int sim_button_state;
- int button_mask = 1 << button->type;
- int ret_val;
-
- /* flip the state of the button */
- sim_button_state = sim_button_state ^ button_mask;
- ret_val = !!(sim_button_state & button_mask);
- /* adjustment for active high/lo */
- if (!(button->flags & BUTTON_FLAG_ACTIVE_HIGH))
- ret_val = !ret_val;
- return ret_val;
+ return !!(sim_button_state & BIT(button->type));
}
#endif
@@ -73,14 +70,14 @@ static int simulated_button_pressed(const struct button_config *button)
*/
static int raw_button_pressed(const struct button_config *button)
{
- int raw_value =
-#ifdef CONFIG_CMD_BUTTON
- siml_btn_presd ?
- simulated_button_pressed(button) :
+ int physical_value = (!!gpio_get_level(button->gpio) ==
+ !!(button->flags & BUTTON_FLAG_ACTIVE_HIGH));
+ int simulated_value = 0;
+#ifdef CONFIG_SIMULATED_BUTTON
+ simulated_value = simulated_button_pressed(button);
#endif
- gpio_get_level(button->gpio);
- return button->flags & BUTTON_FLAG_ACTIVE_HIGH ?
- raw_value : !raw_value;
+
+ return (simulated_value || physical_value);
}
#ifdef CONFIG_BUTTON_TRIGGERED_RECOVERY
@@ -324,7 +321,7 @@ void button_interrupt(enum gpio_signal signal)
}
}
-#ifdef CONFIG_CMD_BUTTON
+#ifdef CONFIG_SIMULATED_BUTTON
static int button_present(enum keyboard_button_type type)
{
int i;
@@ -339,17 +336,54 @@ static int button_present(enum keyboard_button_type type)
static void button_interrupt_simulate(int button)
{
button_interrupt(buttons[button].gpio);
- usleep(buttons[button].debounce_us >> 2);
- button_interrupt(buttons[button].gpio);
}
+static void simulate_button_release_deferred(void)
+{
+ int button_idx;
+
+ /* Release the button */
+ for (button_idx = 0; button_idx < BUTTON_COUNT; button_idx++) {
+ /* Check state for button pressed */
+ if (sim_button_state & BIT(buttons[button_idx].type)) {
+ /* Set state of the button as released */
+ atomic_clear(&sim_button_state,
+ BIT(buttons[button_idx].type));
+
+ button_interrupt_simulate(button_idx);
+ }
+ }
+}
+DECLARE_DEFERRED(simulate_button_release_deferred);
+
+static void simulate_button(uint32_t button_mask, int press_ms)
+{
+ int button_idx;
+
+ /* Press the button */
+ for (button_idx = 0; button_idx < BUTTON_COUNT; button_idx++) {
+ if (button_mask & BIT(button_idx)) {
+ /* Set state of the button as pressed */
+ atomic_or(&sim_button_state,
+ BIT(buttons[button_idx].type));
+
+ button_interrupt_simulate(button_idx);
+ }
+ }
+
+ /* Defer the button release for specified duration */
+ hook_call_deferred(&simulate_button_release_deferred_data,
+ press_ms * MSEC);
+}
+#endif /* #ifdef CONFIG_SIMULATED_BUTTON */
+
+#ifdef CONFIG_CMD_BUTTON
static int console_command_button(int argc, char **argv)
{
int press_ms = 50;
char *e;
int argv_idx;
- int button;
- int button_idx;
+ int button = BUTTON_COUNT;
uint32_t button_mask = 0;
if (argc < 2)
@@ -382,32 +416,39 @@ static int console_command_button(int argc, char **argv)
if (!button_mask)
return EC_SUCCESS;
- siml_btn_presd = 1;
+ simulate_button(button_mask, press_ms);
- /* Press the button(s) */
- for (button_idx = 0; button_idx < BUTTON_COUNT; button_idx++)
- if (button_mask & BIT(button_idx))
- button_interrupt_simulate(button_idx);
+ return EC_SUCCESS;
+}
+DECLARE_CONSOLE_COMMAND(button, console_command_button,
+ "vup|vdown|rec msec",
+ "Simulate button press");
+#endif /* CONFIG_CMD_BUTTON */
- /* Hold the button(s) */
- if (press_ms > 0)
- msleep(press_ms);
+#ifdef CONFIG_HOSTCMD_BUTTON
+static enum ec_status host_command_button(struct host_cmd_handler_args *args)
+{
+ const struct ec_params_button *p = args->params;
+ int idx;
+ uint32_t button_mask = 0;
- /* Release the button(s) */
- for (button_idx = 0; button_idx < BUTTON_COUNT; button_idx++)
- if (button_mask & BIT(button_idx))
- button_interrupt_simulate(button_idx);
+ /* Only available on unlocked systems */
+ if (system_is_locked())
+ return EC_RES_ACCESS_DENIED;
- /* Wait till button processing is finished */
- msleep(100);
+ for (idx = 0; idx < KEYBOARD_BUTTON_COUNT; idx++) {
+ if (p->btn_mask & BIT(idx))
+ button_mask |= BIT(button_present(idx));
+ }
- siml_btn_presd = 0;
- return EC_SUCCESS;
+ simulate_button(button_mask, p->press_ms);
+
+ return EC_RES_SUCCESS;
}
-DECLARE_CONSOLE_COMMAND(button, console_command_button,
- "vup|vdown msec",
- "Simulate button press");
-#endif
+DECLARE_HOST_COMMAND(EC_CMD_BUTTON, host_command_button, EC_VER_MASK(0));
+
+#endif /* CONFIG_HOSTCMD_BUTTON */
+
#ifdef CONFIG_EMULATED_SYSRQ
diff --git a/include/button.h b/include/button.h
index 5f6ffe11c6..bbe4cb44df 100644
--- a/include/button.h
+++ b/include/button.h
@@ -11,28 +11,12 @@
#include "common.h"
#include "compile_time_macros.h"
#include "gpio.h"
+#include "ec_commands.h"
#define BUTTON_FLAG_ACTIVE_HIGH BIT(0)
#define BUTTON_DEBOUNCE_US (30 * MSEC)
-enum keyboard_button_type {
- KEYBOARD_BUTTON_POWER = 0,
- KEYBOARD_BUTTON_VOLUME_DOWN,
- KEYBOARD_BUTTON_VOLUME_UP,
- KEYBOARD_BUTTON_RECOVERY,
- KEYBOARD_BUTTON_CAPSENSE_1,
- KEYBOARD_BUTTON_CAPSENSE_2,
- KEYBOARD_BUTTON_CAPSENSE_3,
- KEYBOARD_BUTTON_CAPSENSE_4,
- KEYBOARD_BUTTON_CAPSENSE_5,
- KEYBOARD_BUTTON_CAPSENSE_6,
- KEYBOARD_BUTTON_CAPSENSE_7,
- KEYBOARD_BUTTON_CAPSENSE_8,
-
- KEYBOARD_BUTTON_COUNT
-};
-
struct button_config {
const char *name;
enum keyboard_button_type type;
diff --git a/include/config.h b/include/config.h
index ad38af54d8..45ca08e6da 100644
--- a/include/config.h
+++ b/include/config.h
@@ -732,6 +732,14 @@
*/
#undef CONFIG_BUTTONS_RUNTIME_CONFIG
+/* Support simulation of a button press using EC tool command */
+#undef CONFIG_HOSTCMD_BUTTON
+/*
+ * Configuration for button simulation i.e. dependent on
+ * CONFIG_HOSTCMD_BUTTON or CONFIG_CMD_BUTTON config.
+ */
+#undef CONFIG_SIMULATED_BUTTON
+
/*
* Capsense chip has buttons, too.
*/
diff --git a/include/ec_commands.h b/include/ec_commands.h
index 530b6cb2d4..5d7dd1926c 100644
--- a/include/ec_commands.h
+++ b/include/ec_commands.h
@@ -6013,6 +6013,43 @@ struct ec_response_get_pd_port_caps {
} __ec_align1;
/*****************************************************************************/
+/*
+ * Button press simulation
+ *
+ * This command is used to simulate a button press.
+ * Supported commands are vup(volume up) vdown(volume down) & rec(recovery)
+ * Time duration for which button needs to be pressed is an optional parameter.
+ *
+ * NOTE: This is only available on unlocked devices for testing purposes only.
+ */
+#define EC_CMD_BUTTON 0x0129
+
+struct ec_params_button {
+ /* Button mask aligned to enum keyboard_button_type */
+ uint32_t btn_mask;
+
+ /* Duration in milliseconds button needs to be pressed */
+ uint32_t press_ms;
+} __ec_align1;
+
+enum keyboard_button_type {
+ KEYBOARD_BUTTON_POWER = 0,
+ KEYBOARD_BUTTON_VOLUME_DOWN = 1,
+ KEYBOARD_BUTTON_VOLUME_UP = 2,
+ KEYBOARD_BUTTON_RECOVERY = 3,
+ KEYBOARD_BUTTON_CAPSENSE_1 = 4,
+ KEYBOARD_BUTTON_CAPSENSE_2 = 5,
+ KEYBOARD_BUTTON_CAPSENSE_3 = 6,
+ KEYBOARD_BUTTON_CAPSENSE_4 = 7,
+ KEYBOARD_BUTTON_CAPSENSE_5 = 8,
+ KEYBOARD_BUTTON_CAPSENSE_6 = 9,
+ KEYBOARD_BUTTON_CAPSENSE_7 = 10,
+ KEYBOARD_BUTTON_CAPSENSE_8 = 11,
+
+ KEYBOARD_BUTTON_COUNT
+};
+
+/*****************************************************************************/
/* The command range 0x200-0x2FF is reserved for Rotor. */
/*****************************************************************************/
diff --git a/util/ectool.c b/util/ectool.c
index c521f94900..c04fddb4c6 100644
--- a/util/ectool.c
+++ b/util/ectool.c
@@ -80,6 +80,8 @@ const char help_str[] =
" Read or write board-specific battery parameter\n"
" boardversion\n"
" Prints the board version\n"
+ " button [vup|vdown|rec] <Delay-ms>\n"
+ " Simulates button press.\n"
" cbi\n"
" Get/Set Cros Board Info\n"
" chargecurrentlimit\n"
@@ -1106,6 +1108,58 @@ int cmd_reboot_ap_on_g3(int argc, char *argv[])
return (rv < 0 ? rv : 0);
}
+int cmd_button(int argc, char *argv[])
+{
+ struct ec_params_button p;
+ char *e;
+ int argv_idx;
+ int button = KEYBOARD_BUTTON_COUNT;
+ int rv;
+
+ if (argc < 2) {
+ fprintf(stderr, "Invalid num param %d.\n", argc);
+ return -1;
+ }
+
+ p.press_ms = 50;
+ p.btn_mask = 0;
+
+ for (argv_idx = 1; argv_idx < argc; argv_idx++) {
+ if (!strcasecmp(argv[argv_idx], "vup"))
+ button = KEYBOARD_BUTTON_VOLUME_UP;
+ else if (!strcasecmp(argv[argv_idx], "vdown"))
+ button = KEYBOARD_BUTTON_VOLUME_DOWN;
+ else if (!strcasecmp(argv[argv_idx], "rec"))
+ button = KEYBOARD_BUTTON_RECOVERY;
+ else {
+ /* If last parameter check if it is an integer. */
+ if (argv_idx == argc - 1) {
+ p.press_ms = strtol(argv[argv_idx], &e, 0);
+ /* If integer, break out of the loop. */
+ if (!*e)
+ break;
+ }
+ button = KEYBOARD_BUTTON_COUNT;
+ }
+
+ if (button == KEYBOARD_BUTTON_COUNT) {
+ fprintf(stderr, "Invalid button input.\n");
+ return -1;
+ }
+
+ p.btn_mask |= (1 << button);
+ }
+ if (!p.btn_mask)
+ return 0;
+
+ rv = ec_command(EC_CMD_BUTTON, 0, &p, sizeof(p), NULL, 0);
+ if (rv < 0)
+ return rv;
+
+ printf("Button(s) %d set to %d ms\n", p.btn_mask, p.press_ms);
+ return 0;
+}
+
int cmd_flash_info(int argc, char *argv[])
{
struct ec_response_flash_info_1 r;
@@ -9428,6 +9482,7 @@ const struct command commands[] = {
{"batterycutoff", cmd_battery_cut_off},
{"batteryparam", cmd_battery_vendor_param},
{"boardversion", cmd_board_version},
+ {"button", cmd_button},
{"cbi", cmd_cbi},
{"chargecurrentlimit", cmd_charge_current_limit},
{"chargecontrol", cmd_charge_control},