Skip to contentSkip to conversation

tools: gpiomon: add initial-state option

PATCH Applied [email protected] 2 participants 2 messages Jan 29 – Jan 30 GPIO

lore
Share & tools
lore
#0 lore raw

PATCH v3 1/1 tools: gpiomon: add initial-state option

From: Shaarang Tyagi <[email protected]>

Add a gpiomon initial-state command line option to display initial line states, this is diplayed before waiting for events. And factoring out the gpioget line status printing code into tools-common.

---
Changes in v2:
- allocation of "values" moved to if block.
- existing variable pollfds was freed.
- option -S changed to -I.
- Added to the unit test.
- Reuse of print_line_vals()

Changes in v3:
- Addition of -N/--numeric switch.
- Dropped "Initial line state(s):" text.
- Unit test now using dut_run and dut_kill.
- Dropped freeing of existing variable pollfds.

---
 tests/scripts/gpiod-bash-test-helper.inc |  0
 tools/gpio-tools-test.bash               | 13 ++++++++++
 tools/gpioget.c                          | 18 +-------------
 tools/gpiomon.c                          | 30 +++++++++++++++++++++++-
 tools/tools-common.c                     | 21 +++++++++++++++++
 tools/tools-common.h                     |  2 ++
 6 files changed, 66 insertions(+), 18 deletions(-)
 mode change 100644 => 100755 tests/scripts/gpiod-bash-test-helper.inc
tests/scripts/gpiod-bash-test-helper.inc +0 -0
old mode 100644
new mode 100755
tools/gpio-tools-test.bash +13 -0
index 898b348..6834f70 100755
@@ -2235,6 +2235,19 @@ test_gpiomon_with_custom_format_unknown_specifier() {
 	output_is "%x"
 }
 
+test_gpiomon_with_initial_state() {
+	gpiosim_chip sim0 num_lines=8
+	gpiosim_set_pull sim0 2 pull-up
+	gpiosim_set_pull sim0 3 pull-up
+	gpiosim_set_pull sim0 5 pull-up
+	gpiosim_set_pull sim0 7 pull-up
+	local sim0=${GPIOSIM_CHIP_NAME[sim0]}
+
+	dut_run gpiomon --initial-state --chip "$sim0" 0 1 2 3 4 5 6 7
+	dut_read
+	dut_kill
+	output_is "\"0\"=inactive \"1\"=inactive \"2\"=active \"3\"=active \"4\"=inactive \"5\"=active \"6\"=inactive \"7\"=active"
+}
 #
 # gpionotify test cases
 #
tools/gpioget.c +1 -17
index bad7667..de1dbdf 100644
@@ -139,12 +139,10 @@ int main(int argc, char **argv)
 	struct gpiod_line_config *line_cfg;
 	struct line_resolver *resolver;
 	enum gpiod_line_value *values;
-	struct resolved_line *line;
 	struct gpiod_chip *chip;
 	unsigned int *offsets;
 	int i, num_lines, ret;
 	struct config cfg;
-	const char *fmt;
 
 	set_prog_name(argv[0]);
 	i = parse_config(argc, argv, &cfg);
@@ -216,21 +214,7 @@ int main(int argc, char **argv)
 		gpiod_line_request_release(request);
 		gpiod_chip_close(chip);
 	}
-
-	fmt = cfg.unquoted ? "%s=%s" : "\"%s\"=%s";
-
-	for (i = 0; i < resolver->num_lines; i++) {
-		line = &resolver->lines[i];
-		if (cfg.numeric)
-			printf("%d", line->value);
-		else
-			printf(fmt, line->id,
-			       line->value ? "active" : "inactive");
-
-		if (i != resolver->num_lines - 1)
-			printf(" ");
-	}
-	printf("\n");
+	print_line_vals(resolver, cfg.unquoted, cfg.numeric);
 
 	free_line_resolver(resolver);
 	gpiod_request_config_free(req_cfg);
tools/gpiomon.c +29 -1
index 88b5ccf..a62955b 100644
@@ -32,6 +32,8 @@ struct config {
 	enum gpiod_line_clock event_clock;
 	int timestamp_fmt;
 	long long idle_timeout;
+	bool initial_state;
+	bool numeric;
 };
 
 static void print_help(void)
@@ -69,6 +71,8 @@ static void print_help(void)
 	printf("  -p, --debounce-period <period>\n");
 	printf("\t\t\tdebounce the line(s) with the specified period\n");
 	printf("  -q, --quiet\t\tdon't generate any output\n");
+	printf("  -I, --initial-state\t\tprint initial states of the lines\n");
+	printf("  -N, --numeric\t\tdisplay line values as '0' (inactive) or '1' (active)\n");
 	printf("  -s, --strict\t\tabort if requested line names are not unique\n");
 	printf("      --unquoted\tdon't quote line or consumer names\n");
 	printf("      --utc\t\tformat event timestamps as UTC (default for 'realtime')\n");
@@ -113,7 +117,7 @@ static int parse_event_clock_or_die(const char *option)
 
 static int parse_config(int argc, char **argv, struct config *cfg)
 {
-	static const char *const shortopts = "+b:c:C:e:E:hF:ln:p:qshv";
+	static const char *const shortopts = "+b:c:C:e:E:hF:ln:p:qshvIN";
 
 	const struct option longopts[] = {
 		{ "active-low",	no_argument,	NULL,		'l' },
@@ -136,6 +140,8 @@ static int parse_config(int argc, char **argv, struct config *cfg)
 		{ "unquoted",	no_argument,	NULL,		'Q' },
 		{ "utc",	no_argument,	&cfg->timestamp_fmt,	1 },
 		{ "version",	no_argument,	NULL,		'v' },
+		{ "initial-state",	no_argument,	NULL,		'I' },
+		{ "numeric",	no_argument,	NULL,		'N' },
 		{ GETOPT_NULL_LONGOPT },
 	};
 
@@ -197,6 +203,12 @@ static int parse_config(int argc, char **argv, struct config *cfg)
 		case 's':
 			cfg->strict = true;
 			break;
+		case 'I':
+			cfg->initial_state = true;
+			break;
+		case 'N':
+			cfg->numeric = true;
+			break;
 		case 'h':
 			print_help();
 			exit(EXIT_SUCCESS);
@@ -363,6 +375,7 @@ int main(int argc, char **argv)
 	int num_lines, events_done = 0;
 	struct gpiod_edge_event *event;
 	struct line_resolver *resolver;
+	enum gpiod_line_value *values;
 	struct timespec idle_timeout;
 	struct gpiod_chip *chip;
 	struct pollfd *pollfds;
@@ -423,6 +436,7 @@ int main(int argc, char **argv)
 	requests = calloc(resolver->num_chips, sizeof(*requests));
 	pollfds = calloc(resolver->num_chips, sizeof(*pollfds));
 	offsets = calloc(resolver->num_lines, sizeof(*offsets));
+
 	if (!requests || !pollfds || !offsets)
 		die("out of memory");
 
@@ -445,6 +459,20 @@ int main(int argc, char **argv)
 			die_perror("unable to request lines on chip %s",
 				   resolver->chips[i].path);
 
+		if (cfg.initial_state) {
+			values = calloc(resolver->num_lines, sizeof(*values));
+			if (!values)
+				die("out of memory");
+
+			ret = gpiod_line_request_get_values(requests[i], values);
+			if (ret)
+				die_perror("unable to read GPIO line values");
+
+			set_line_values(resolver, i, values);
+			print_line_vals(resolver, cfg.unquoted, cfg.numeric);
+			free(values);
+		}
+
 		pollfds[i].fd = gpiod_line_request_get_fd(requests[i]);
 		pollfds[i].events = POLLIN;
 		gpiod_chip_close(chip);
tools/tools-common.c +21 -0
index 8c2d5bc..b8d821a 100644
@@ -402,6 +402,27 @@ void print_line_id(struct line_resolver *resolver, int chip_num,
 	printf(fmt, lname);
 }
 
+void print_line_vals(struct line_resolver *resolver, bool is_unquoted,
+			bool is_numeric)
+{
+	int i;
+	const char *fmt = is_unquoted ? "%s=%s" : "\"%s\"=%s";
+
+	for (i = 0; i < resolver->num_lines; i++) {
+		struct resolved_line *line = &resolver->lines[i];
+
+		if (is_numeric)
+			printf("%d", line->value);
+		else
+			printf(fmt, line->id,
+			       line->value ? "active" : "inactive");
+
+		if (i != resolver->num_lines - 1)
+			printf(" ");
+	}
+	printf("\n");
+}
+
 static int chip_dir_filter(const struct dirent *entry)
 {
 	struct stat sb;
tools/tools-common.h +2 -0
index bc63080..479373a 100644
@@ -99,6 +99,8 @@ void print_event_time(uint64_t evtime, int format);
 void print_line_attributes(struct gpiod_line_info *info, bool unquoted_strings);
 void print_line_id(struct line_resolver *resolver, int chip_num,
 		   unsigned int offset, const char *chip_id, bool unquoted);
+void print_line_vals(struct line_resolver *resolver, bool is_unquoted,
+			bool is_numeric);
 bool chip_path_lookup(const char *id, char **path_ptr);
 int chip_paths(const char *id, char ***paths_ptr);
 int all_chip_paths(char ***paths_ptr);
#1 lore raw
Quoted 5 lines · On Thu, 29 Jan 2026 22:01:39 +0530, [email protected] wrote:

Add a gpiomon initial-state command line option to display initial line states, this is diplayed before waiting for events. And factoring out the gpioget line status printing code into tools-common.

Applied, thanks!

[1/1] tools: gpiomon: add initial-state option

      commit: caf0bff354c8b03eaf070404ccb833265d50c019

Best regards,

Signature · 1 line
Bartosz Golaszewski <[email protected]>