1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (c) 2023 Linaro Ltd.
4  *   Author: Casey Connolly <casey.connolly@linaro.org>
5  */
6 
7 #include <button.h>
8 #include <command.h>
9 #include <env.h>
10 #include <log.h>
11 #include <stdio.h>
12 
13 /* Some sane limit "just in case" */
14 #define MAX_BTN_CMDS 32
15 
16 struct button_cmd {
17 	bool pressed;
18 	const char *btn_name;
19 	const char *cmd;
20 };
21 
22 /*
23  * Button commands are set via environment variables, e.g.:
24  * button_cmd_N_name=Volume Up
25  * button_cmd_N=fastboot usb 0
26  *
27  * This function will retrieve the command for the given button N
28  * and populate the cmd struct with the command string and pressed
29  * state of the button.
30  *
31  * Returns 1 if a command was found, 0 otherwise.
32  */
get_button_cmd(int n,struct button_cmd * cmd)33 static int get_button_cmd(int n, struct button_cmd *cmd)
34 {
35 	const char *cmd_str;
36 	struct udevice *btn = NULL;
37 	char buf[24];
38 
39 	snprintf(buf, sizeof(buf), "button_cmd_%d_name", n);
40 	cmd->btn_name = env_get(buf);
41 	if (!cmd->btn_name)
42 		return 0;
43 
44 	button_get_by_label(cmd->btn_name, &btn);
45 	if (!btn) {
46 		log_err("No button labelled '%s'\n", cmd->btn_name);
47 		return 0;
48 	}
49 
50 	cmd->pressed = button_get_state(btn) == BUTTON_ON;
51 	/* If the button isn't pressed then cmd->cmd will be unused so don't waste
52 	 * cycles reading it
53 	 */
54 	if (!cmd->pressed)
55 		return 1;
56 
57 	snprintf(buf, sizeof(buf), "button_cmd_%d", n);
58 	cmd_str = env_get(buf);
59 	if (!cmd_str) {
60 		log_err("No command set for button '%s'\n", cmd->btn_name);
61 		return 0;
62 	}
63 
64 	cmd->cmd = cmd_str;
65 
66 	return 1;
67 }
68 
process_button_cmds(void)69 void process_button_cmds(void)
70 {
71 	struct button_cmd cmd = {0};
72 	int i = 0;
73 
74 	while (get_button_cmd(i++, &cmd) && i < MAX_BTN_CMDS) {
75 		if (!cmd.pressed)
76 			continue;
77 
78 		log_info("BTN '%s'> %s\n", cmd.btn_name, cmd.cmd);
79 		run_command(cmd.cmd, CMD_FLAG_ENV);
80 		/* Don't run commands for multiple buttons */
81 		return;
82 	}
83 }
84