1 /*
2  * Copyright (c) 2018 Intel Corporation
3  * Copyright (c) 2021 Dennis Ruffer <daruffer@gmail.com>
4  * Copyright (c) 2023 Nick Ward <nix.ward@gmail.com>
5  *
6  * SPDX-License-Identifier: Apache-2.0
7  */
8 
9 #include <zephyr/drivers/gpio.h>
10 #include <zephyr/shell/shell.h>
11 
12 #include <stdio.h>
13 
14 #define ARGV_DEV 1
15 #define ARGV_PIN 2
16 #define ARGV_CONF 3
17 #define ARGV_VALUE 3
18 #define ARGV_VENDOR_SPECIFIC 4
19 
20 #define NGPIOS_UNKNOWN -1
21 #define PIN_NOT_FOUND UINT8_MAX
22 
23 /* Pin syntax maximum length */
24 #define PIN_SYNTAX_MAX 32
25 #define PIN_NUM_MAX 4
26 
27 struct gpio_ctrl {
28 	const struct device *dev;
29 	int8_t ngpios;
30 	gpio_port_pins_t reserved_mask;
31 	const char **line_names;
32 	uint8_t line_names_len;
33 	const union shell_cmd_entry *subcmd;
34 };
35 
36 struct sh_gpio {
37 	const struct device *dev;
38 	gpio_pin_t pin;
39 };
40 /*
41  * Find idx-th pin reference from the set of non reserved
42  * pin numbers and provided line names.
43  */
port_pin_get(gpio_port_pins_t reserved_mask,const char ** line_names,uint8_t line_names_len,size_t idx,struct shell_static_entry * entry)44 static void port_pin_get(gpio_port_pins_t reserved_mask, const char **line_names,
45 			 uint8_t line_names_len, size_t idx, struct shell_static_entry *entry)
46 {
47 	static char pin_syntax[PIN_SYNTAX_MAX];
48 	static char pin_num[PIN_NUM_MAX];
49 	const char *name;
50 	gpio_pin_t pin;
51 	bool reserved;
52 
53 	entry->handler = NULL;
54 
55 	/* Find allowed numeric pin reference */
56 	for (pin = 0; pin < GPIO_MAX_PINS_PER_PORT; pin++) {
57 		reserved = ((BIT64(pin) & reserved_mask) != 0);
58 		if (!reserved) {
59 			if (idx == 0) {
60 				break;
61 			}
62 			idx--;
63 		}
64 	}
65 
66 	if (pin < GPIO_MAX_PINS_PER_PORT) {
67 		sprintf(pin_num, "%u", pin);
68 		if ((pin < line_names_len) && (strlen(line_names[pin]) > 0)) {
69 			/* pin can be specified by line name */
70 			name = line_names[pin];
71 			for (int i = 0; i < (sizeof(pin_syntax) - 1); i++) {
72 				/*
73 				 * For line-name tab completion to work replace any
74 				 * space characters with '_'.
75 				 */
76 				pin_syntax[i] = (name[i] != ' ') ? name[i] : '_';
77 				if (name[i] == '\0') {
78 					break;
79 				}
80 			}
81 			pin_syntax[sizeof(pin_syntax) - 1] = '\0';
82 			entry->syntax = pin_syntax;
83 			entry->help = pin_num;
84 		} else {
85 			/* fallback to pin specified by pin number */
86 			entry->syntax = pin_num;
87 			entry->help = NULL;
88 		}
89 	} else {
90 		/* No more pins */
91 		entry->syntax = NULL;
92 		entry->help = NULL;
93 	}
94 }
95 
96 #define GPIO_DT_RESERVED_RANGES_NGPIOS_SHELL(node_id)                                              \
97 	COND_CODE_1(DT_NODE_HAS_PROP(node_id, ngpios),                                             \
98 		    (GPIO_DT_RESERVED_RANGES_NGPIOS(node_id, DT_PROP(node_id, ngpios))),           \
99 		    (GPIO_MAX_PINS_PER_PORT))
100 
101 #define GPIO_CTRL_PIN_GET_FN(node_id)                                                              \
102 	static const char *node_id##line_names[] = DT_PROP_OR(node_id, gpio_line_names, {NULL});   \
103                                                                                                    \
104 	static void node_id##cmd_gpio_pin_get(size_t idx, struct shell_static_entry *entry);       \
105                                                                                                    \
106 	SHELL_DYNAMIC_CMD_CREATE(node_id##sub_gpio_pin, node_id##cmd_gpio_pin_get);                \
107                                                                                                    \
108 	static void node_id##cmd_gpio_pin_get(size_t idx, struct shell_static_entry *entry)        \
109 	{                                                                                          \
110 		gpio_port_pins_t reserved_mask = GPIO_DT_RESERVED_RANGES_NGPIOS_SHELL(node_id);    \
111 		uint8_t line_names_len = DT_PROP_LEN_OR(node_id, gpio_line_names, 0);              \
112                                                                                                    \
113 		port_pin_get(reserved_mask, node_id##line_names, line_names_len, idx, entry);      \
114 		entry->subcmd = NULL;                                                              \
115 	}
116 
117 #define IS_GPIO_CTRL_PIN_GET(node_id)                                                              \
118 	COND_CODE_1(DT_PROP(node_id, gpio_controller), (GPIO_CTRL_PIN_GET_FN(node_id)), ())
119 
120 DT_FOREACH_STATUS_OKAY_NODE(IS_GPIO_CTRL_PIN_GET)
121 
122 #define GPIO_CTRL_LIST_ENTRY(node_id)                                                              \
123 	{                                                                                          \
124 		.dev = DEVICE_DT_GET(node_id),                                                     \
125 		.ngpios = DT_PROP_OR(node_id, ngpios, NGPIOS_UNKNOWN),                             \
126 		.reserved_mask = GPIO_DT_RESERVED_RANGES_NGPIOS_SHELL(node_id),                    \
127 		.line_names = node_id##line_names,                                                 \
128 		.line_names_len = DT_PROP_LEN_OR(node_id, gpio_line_names, 0),                     \
129 		.subcmd = &node_id##sub_gpio_pin,                                                  \
130 	},
131 
132 #define IS_GPIO_CTRL_LIST(node_id)                                                                 \
133 	COND_CODE_1(DT_PROP(node_id, gpio_controller), (GPIO_CTRL_LIST_ENTRY(node_id)), ())
134 
135 static const struct gpio_ctrl gpio_list[] = {DT_FOREACH_STATUS_OKAY_NODE(IS_GPIO_CTRL_LIST)};
136 
get_gpio_ctrl(const char * name)137 static const struct gpio_ctrl *get_gpio_ctrl(const char *name)
138 {
139 	size_t i;
140 	const struct device *dev = shell_device_get_binding(name);
141 
142 	if (dev == NULL) {
143 		return NULL;
144 	}
145 
146 	for (i = 0; i < ARRAY_SIZE(gpio_list); i++) {
147 		if (gpio_list[i].dev == dev) {
148 			return &gpio_list[i];
149 		}
150 	}
151 
152 	return NULL;
153 }
154 
line_cmp(const char * input,const char * line_name)155 int line_cmp(const char *input, const char *line_name)
156 {
157 	int i = 0;
158 
159 	while (true) {
160 		if ((input[i] == '_') && (line_name[i] == ' ')) {
161 			/* Allow input underscore to match line_name space */
162 		} else if (input[i] != line_name[i]) {
163 			return (input[i] > line_name[i]) ? 1 : -1;
164 		} else if (line_name[i] == '\0') {
165 			return 0;
166 		}
167 		i++;
168 	}
169 }
170 
get_gpio_pin(const struct shell * sh,const struct gpio_ctrl * ctrl,char * line_name)171 static int get_gpio_pin(const struct shell *sh, const struct gpio_ctrl *ctrl, char *line_name)
172 {
173 	gpio_pin_t pin = PIN_NOT_FOUND;
174 	gpio_pin_t i;
175 	int result;
176 
177 	for (i = 0; i < ctrl->ngpios; i++) {
178 		result = line_cmp(line_name, ctrl->line_names[i]);
179 		if (result == 0) {
180 			if ((BIT64(i) & ctrl->reserved_mask) != 0) {
181 				shell_error(sh, "Reserved pin");
182 				return -EACCES;
183 			} else if (pin == PIN_NOT_FOUND) {
184 				pin = i;
185 			} else {
186 				shell_error(sh, "Line name ambiguous");
187 				return -EFAULT;
188 			}
189 		}
190 	}
191 
192 	if (pin == PIN_NOT_FOUND) {
193 		shell_error(sh, "Line name not found: '%s'", line_name);
194 		return -ENOENT;
195 	}
196 
197 	return pin;
198 }
199 
get_sh_gpio(const struct shell * sh,char ** argv,struct sh_gpio * gpio)200 static int get_sh_gpio(const struct shell *sh, char **argv, struct sh_gpio *gpio)
201 {
202 	const struct gpio_ctrl *ctrl;
203 	int ret = 0;
204 	int pin;
205 
206 	ctrl = get_gpio_ctrl(argv[ARGV_DEV]);
207 	if (ctrl == NULL) {
208 		shell_error(sh, "unknown gpio controller: %s", argv[ARGV_DEV]);
209 		return -EINVAL;
210 	}
211 	gpio->dev = ctrl->dev;
212 	pin = shell_strtoul(argv[ARGV_PIN], 0, &ret);
213 	if (ret != 0) {
214 		pin = get_gpio_pin(sh, ctrl, argv[ARGV_PIN]);
215 		if (pin < 0) {
216 			return pin;
217 		}
218 	} else if ((BIT64(pin) & ctrl->reserved_mask) != 0) {
219 		shell_error(sh, "Reserved pin");
220 		return -EACCES;
221 	}
222 	gpio->pin = pin;
223 
224 	return 0;
225 }
226 
cmd_gpio_conf(const struct shell * sh,size_t argc,char ** argv,void * data)227 static int cmd_gpio_conf(const struct shell *sh, size_t argc, char **argv, void *data)
228 {
229 	gpio_flags_t flags = 0;
230 	gpio_flags_t vendor_specific;
231 	struct sh_gpio gpio;
232 	int ret = 0;
233 
234 	ret = get_sh_gpio(sh, argv, &gpio);
235 	if (ret != 0) {
236 		shell_help(sh);
237 		return SHELL_CMD_HELP_PRINTED;
238 	}
239 
240 	for (int i = 0; i < strlen(argv[ARGV_CONF]); i++) {
241 		switch (argv[ARGV_CONF][i]) {
242 		case 'i':
243 			flags |= GPIO_INPUT;
244 			break;
245 		case 'o':
246 			flags |= GPIO_OUTPUT;
247 			break;
248 		case 'u':
249 			flags |= GPIO_PULL_UP;
250 			break;
251 		case 'd':
252 			flags |= GPIO_PULL_DOWN;
253 			break;
254 		case 'h':
255 			flags |= GPIO_ACTIVE_HIGH;
256 			break;
257 		case 'l':
258 			flags |= GPIO_ACTIVE_LOW;
259 			break;
260 		case '0':
261 			flags |= GPIO_OUTPUT_INIT_LOGICAL | GPIO_OUTPUT_INIT_LOW;
262 			break;
263 		case '1':
264 			flags |= GPIO_OUTPUT_INIT_LOGICAL | GPIO_OUTPUT_INIT_HIGH;
265 			break;
266 		default:
267 			shell_error(sh, "Unknown: '%c'", argv[ARGV_CONF][i]);
268 			shell_help(sh);
269 			return SHELL_CMD_HELP_PRINTED;
270 		}
271 	}
272 
273 	if (((flags & GPIO_INPUT) != 0) == ((flags & GPIO_OUTPUT) != 0)) {
274 		shell_error(sh, "must be either input or output");
275 		shell_help(sh);
276 		return SHELL_CMD_HELP_PRINTED;
277 	}
278 
279 	if (((flags & GPIO_PULL_UP) != 0) && ((flags & GPIO_PULL_DOWN) != 0)) {
280 		shell_error(sh, "cannot be pull up and pull down");
281 		shell_help(sh);
282 		return SHELL_CMD_HELP_PRINTED;
283 	}
284 
285 	if (((flags & GPIO_ACTIVE_LOW) != 0) && ((flags & GPIO_ACTIVE_HIGH) != 0)) {
286 		shell_error(sh, "cannot be active low and active high");
287 		shell_help(sh);
288 		return SHELL_CMD_HELP_PRINTED;
289 	}
290 
291 	if ((flags & GPIO_OUTPUT) != 0) {
292 		/* Default to active high if not specified */
293 		if ((flags & (GPIO_ACTIVE_LOW | GPIO_ACTIVE_HIGH)) == 0) {
294 			flags |= GPIO_ACTIVE_HIGH;
295 		}
296 		/* Default to initialisation to logic 0 if not specified */
297 		if ((flags & GPIO_OUTPUT_INIT_LOGICAL) == 0) {
298 			flags |= GPIO_OUTPUT_INIT_LOGICAL | GPIO_OUTPUT_INIT_LOW;
299 		}
300 	}
301 
302 	if (((flags & GPIO_INPUT) != 0) && ((flags & GPIO_OUTPUT_INIT_LOGICAL) != 0)) {
303 		shell_error(sh, "an input cannot be initialised to a logic level");
304 		shell_help(sh);
305 		return SHELL_CMD_HELP_PRINTED;
306 	}
307 
308 	if (((flags & GPIO_OUTPUT_INIT_LOW) != 0) && ((flags & GPIO_OUTPUT_INIT_HIGH) != 0)) {
309 		shell_error(sh, "cannot initialise to logic 0 and logic 1");
310 		shell_help(sh);
311 		return SHELL_CMD_HELP_PRINTED;
312 	}
313 
314 	if (argc == 5) {
315 		vendor_specific = shell_strtoul(argv[ARGV_VENDOR_SPECIFIC], 0, &ret);
316 		if ((ret == 0) && ((vendor_specific & ~(0xFF00U)) == 0)) {
317 			flags |= vendor_specific;
318 		} else {
319 			/*
320 			 * See include/zephyr/dt-bindings/gpio/ for the
321 			 * available flags for your vendor.
322 			 */
323 			shell_error(sh, "vendor specific flags must be within "
324 					"the mask 0xFF00");
325 			shell_help(sh);
326 			return SHELL_CMD_HELP_PRINTED;
327 		}
328 	}
329 
330 	ret = gpio_pin_configure(gpio.dev, gpio.pin, flags);
331 	if (ret != 0) {
332 		shell_error(sh, "error: %d", ret);
333 		return ret;
334 	}
335 
336 	return 0;
337 }
338 
cmd_gpio_get(const struct shell * sh,size_t argc,char ** argv)339 static int cmd_gpio_get(const struct shell *sh, size_t argc, char **argv)
340 {
341 	struct sh_gpio gpio;
342 	int value;
343 	int ret;
344 
345 	ret = get_sh_gpio(sh, argv, &gpio);
346 	if (ret != 0) {
347 		shell_help(sh);
348 		return SHELL_CMD_HELP_PRINTED;
349 	}
350 
351 	value = gpio_pin_get(gpio.dev, gpio.pin);
352 	if (value >= 0) {
353 		shell_print(sh, "%u", value);
354 	} else {
355 		shell_error(sh, "error: %d", value);
356 		return value;
357 	}
358 
359 	return 0;
360 }
361 
cmd_gpio_set(const struct shell * sh,size_t argc,char ** argv)362 static int cmd_gpio_set(const struct shell *sh, size_t argc, char **argv)
363 {
364 	struct sh_gpio gpio;
365 	unsigned long value;
366 	int ret = 0;
367 
368 	ret = get_sh_gpio(sh, argv, &gpio);
369 	if (ret != 0) {
370 		shell_help(sh);
371 		return SHELL_CMD_HELP_PRINTED;
372 	}
373 
374 	value = shell_strtoul(argv[ARGV_VALUE], 0, &ret);
375 	if (ret != 0) {
376 		shell_help(sh);
377 		return SHELL_CMD_HELP_PRINTED;
378 	}
379 
380 	ret = gpio_pin_set(gpio.dev, gpio.pin, value != 0);
381 	if (ret != 0) {
382 		shell_error(sh, "error: %d", ret);
383 		return ret;
384 	}
385 
386 	return 0;
387 }
388 
cmd_gpio_toggle(const struct shell * sh,size_t argc,char ** argv)389 static int cmd_gpio_toggle(const struct shell *sh, size_t argc, char **argv)
390 {
391 	struct sh_gpio gpio;
392 	int ret = 0;
393 
394 	ret = get_sh_gpio(sh, argv, &gpio);
395 	if (ret != 0) {
396 		shell_help(sh);
397 		return SHELL_CMD_HELP_PRINTED;
398 	}
399 
400 	ret = gpio_pin_toggle(gpio.dev, gpio.pin);
401 	if (ret != 0) {
402 		shell_error(sh, "error: %d", ret);
403 		return ret;
404 	}
405 
406 	return 0;
407 }
408 
cmd_gpio_devices(const struct shell * sh,size_t argc,char ** argv)409 static int cmd_gpio_devices(const struct shell *sh, size_t argc, char **argv)
410 {
411 	size_t i;
412 
413 	shell_fprintf(sh, SHELL_NORMAL, "%-16s Other names\n", "Device");
414 
415 	for (i = 0; i < ARRAY_SIZE(gpio_list); i++) {
416 		const struct device *dev = gpio_list[i].dev;
417 
418 		shell_fprintf(sh, SHELL_NORMAL, "%-16s", dev->name);
419 
420 #ifdef CONFIG_DEVICE_DT_METADATA
421 		const struct device_dt_nodelabels *nl = device_get_dt_nodelabels(dev);
422 
423 		if (nl != NULL && nl->num_nodelabels > 0) {
424 			for (size_t j = 0; j < nl->num_nodelabels; j++) {
425 				const char *nodelabel = nl->nodelabels[j];
426 
427 				shell_fprintf(sh, SHELL_NORMAL, " %s", nodelabel);
428 			}
429 		}
430 #endif
431 
432 		shell_fprintf(sh, SHELL_NORMAL, "\n");
433 	}
434 
435 	return 0;
436 }
437 
438 /* 500 msec = 1/2 sec */
439 #define SLEEP_TIME_MS   500
440 
cmd_gpio_blink(const struct shell * sh,size_t argc,char ** argv)441 static int cmd_gpio_blink(const struct shell *sh, size_t argc, char **argv)
442 {
443 	bool msg_one_shot = true;
444 	struct sh_gpio gpio;
445 	size_t count;
446 	char data;
447 	int ret;
448 
449 	ret = get_sh_gpio(sh, argv, &gpio);
450 	if (ret != 0) {
451 		shell_help(sh);
452 		return SHELL_CMD_HELP_PRINTED;
453 	}
454 
455 	/* dummy read to clear any pending input */
456 	(void)sh->iface->api->read(sh->iface, &data, sizeof(data), &count);
457 
458 	while (true) {
459 		(void)sh->iface->api->read(sh->iface, &data, sizeof(data), &count);
460 		if (count != 0) {
461 			break;
462 		}
463 		ret = gpio_pin_toggle(gpio.dev, gpio.pin);
464 		if (ret != 0) {
465 			shell_error(sh, "%d", ret);
466 			break;
467 		} else if (msg_one_shot) {
468 			msg_one_shot = false;
469 			shell_print(sh, "Hit any key to exit");
470 		}
471 		k_msleep(SLEEP_TIME_MS);
472 	}
473 
474 	return 0;
475 }
476 
device_name_get(size_t idx,struct shell_static_entry * entry)477 static void device_name_get(size_t idx, struct shell_static_entry *entry)
478 {
479 	if (idx >= ARRAY_SIZE(gpio_list)) {
480 		entry->syntax = NULL;
481 		return;
482 	}
483 
484 	entry->syntax = gpio_list[idx].dev->name;
485 	entry->handler = NULL;
486 	entry->help = "Device";
487 	entry->subcmd = gpio_list[idx].subcmd;
488 }
489 
490 SHELL_DYNAMIC_CMD_CREATE(sub_gpio_dev, device_name_get);
491 
492 struct pin_info {
493 	const struct device *dev;
494 	bool reserved;
495 	gpio_pin_t pin;
496 	const char *line_name;
497 };
498 
499 struct pin_order_user_data {
500 	const struct shell *sh;
501 	struct pin_info prev;
502 	struct pin_info next;
503 };
504 
505 typedef void (*pin_foreach_func_t)(const struct pin_info *info, void *user_data);
506 
print_gpio_ctrl_info(const struct shell * sh,const struct gpio_ctrl * ctrl)507 static void print_gpio_ctrl_info(const struct shell *sh, const struct gpio_ctrl *ctrl)
508 {
509 	gpio_pin_t pin;
510 	bool reserved;
511 	const char *line_name;
512 
513 	shell_print(sh, " ngpios: %u", ctrl->ngpios);
514 	shell_print(sh, " Reserved pin mask: 0x%08X", ctrl->reserved_mask);
515 
516 	shell_print(sh, "");
517 
518 	shell_print(sh, " Reserved  Pin  Line Name");
519 	for (pin = 0; pin < ctrl->ngpios; pin++) {
520 		reserved = (BIT64(pin) & ctrl->reserved_mask) != 0;
521 		if (pin < ctrl->line_names_len) {
522 			line_name = ctrl->line_names[pin];
523 		} else {
524 			line_name = "";
525 		}
526 		shell_print(sh, "     %c     %2u    %s", reserved ? '*' : ' ', pin, line_name);
527 	}
528 }
529 
foreach_pin(pin_foreach_func_t func,void * user_data)530 static void foreach_pin(pin_foreach_func_t func, void *user_data)
531 {
532 	gpio_port_pins_t reserved_mask;
533 	struct pin_info info;
534 	gpio_pin_t pin;
535 	size_t i;
536 
537 	for (i = 0; i < ARRAY_SIZE(gpio_list); i++) {
538 		for (pin = 0; pin < gpio_list[i].ngpios; pin++) {
539 			info.dev = gpio_list[i].dev;
540 			reserved_mask = gpio_list[i].reserved_mask;
541 			info.reserved = (BIT64(pin) & reserved_mask) != 0;
542 			info.pin = pin;
543 			if (pin < gpio_list[i].line_names_len) {
544 				info.line_name = gpio_list[i].line_names[pin];
545 			} else {
546 				info.line_name = "";
547 			}
548 			func(&info, user_data);
549 		}
550 	}
551 }
552 
pin_cmp(const struct pin_info * a,const struct pin_info * b)553 static int pin_cmp(const struct pin_info *a, const struct pin_info *b)
554 {
555 	int result = strcmp(a->line_name, b->line_name);
556 
557 	if (result != 0) {
558 		return result;
559 	}
560 	result = strcmp(a->dev->name, b->dev->name);
561 	if (result != 0) {
562 		return result;
563 	}
564 	result = (int)a->pin - (int)b->pin;
565 
566 	return result;
567 }
568 
pin_get_next(const struct pin_info * info,void * user_data)569 static void pin_get_next(const struct pin_info *info, void *user_data)
570 {
571 	struct pin_order_user_data *data = user_data;
572 	int result;
573 
574 	if (data->prev.line_name != NULL) {
575 		result = pin_cmp(info, &data->prev);
576 	} else {
577 		result = 1;
578 	}
579 	if (result > 0) {
580 		if (data->next.line_name == NULL) {
581 			data->next = *info;
582 			return;
583 		}
584 		result = pin_cmp(info, &data->next);
585 		if (result < 0) {
586 			data->next = *info;
587 		}
588 	}
589 }
590 
pin_ordered(const struct pin_info * info,void * user_data)591 static void pin_ordered(const struct pin_info *info, void *user_data)
592 {
593 	struct pin_order_user_data *data = user_data;
594 
595 	ARG_UNUSED(info);
596 
597 	foreach_pin(pin_get_next, data);
598 
599 	shell_print(data->sh, "   %-12s %-8c %-16s %2u",
600 		    data->next.line_name,
601 		    data->next.reserved ? '*' : ' ',
602 		    data->next.dev->name,
603 		    data->next.pin);
604 
605 	data->prev = data->next;
606 	data->next.line_name = NULL;
607 }
608 
print_ordered_info(const struct shell * sh)609 static void print_ordered_info(const struct shell *sh)
610 {
611 	struct pin_order_user_data data = {0};
612 
613 	data.sh = sh;
614 
615 	shell_print(sh, "  %-12s %-8s %-16s %-3s",
616 		"Line", "Reserved", "Device", "Pin");
617 
618 	foreach_pin(pin_ordered, &data);
619 }
620 
cmd_gpio_info(const struct shell * sh,size_t argc,char ** argv)621 static int cmd_gpio_info(const struct shell *sh, size_t argc, char **argv)
622 {
623 	const struct gpio_ctrl *ctrl = get_gpio_ctrl(argv[ARGV_DEV]);
624 
625 	if (ctrl == NULL) {
626 		/* No device specified */
627 		print_ordered_info(sh);
628 		return 0;
629 	}
630 
631 	print_gpio_ctrl_info(sh, ctrl);
632 
633 	return 0;
634 }
635 
636 SHELL_STATIC_SUBCMD_SET_CREATE(sub_gpio,
637 	SHELL_CMD_ARG(conf, &sub_gpio_dev,
638 		"Configure GPIO pin\n"
639 		"Usage: gpio conf <device> <pin> <configuration <i|o>[u|d][h|l][0|1]> [vendor specific]\n"
640 		"<i|o> - input|output\n"
641 		"[u|d] - pull up|pull down, otherwise open\n"
642 		"[h|l] - active high|active low, otherwise defaults to active high\n"
643 		"[0|1] - initialise to logic 0|logic 1, otherwise defaults to logic 0\n"
644 		"[vendor specific] - configuration flags within the mask 0xFF00\n"
645 		"                    see include/zephyr/dt-bindings/gpio/",
646 		cmd_gpio_conf, 4, 1),
647 	SHELL_CMD_ARG(get, &sub_gpio_dev,
648 		"Get GPIO pin value\n"
649 		"Usage: gpio get <device> <pin>", cmd_gpio_get, 3, 0),
650 	SHELL_CMD_ARG(set, &sub_gpio_dev,
651 		"Set GPIO pin value\n"
652 		"Usage: gpio set <device> <pin> <level 0|1>", cmd_gpio_set, 4, 0),
653 	SHELL_COND_CMD_ARG(CONFIG_GPIO_SHELL_TOGGLE_CMD, toggle, &sub_gpio_dev,
654 		"Toggle GPIO pin\n"
655 		"Usage: gpio toggle <device> <pin>", cmd_gpio_toggle, 3, 0),
656 	SHELL_CMD(devices, NULL,
657 		"List all GPIO devices\n"
658 		"Usage: gpio devices", cmd_gpio_devices),
659 	SHELL_COND_CMD_ARG(CONFIG_GPIO_SHELL_BLINK_CMD, blink, &sub_gpio_dev,
660 		"Blink GPIO pin\n"
661 		"Usage: gpio blink <device> <pin>", cmd_gpio_blink, 3, 0),
662 	SHELL_COND_CMD_ARG(CONFIG_GPIO_SHELL_INFO_CMD, info, &sub_gpio_dev,
663 		"GPIO Information\n"
664 		"Usage: gpio info [device]", cmd_gpio_info, 1, 1),
665 	SHELL_SUBCMD_SET_END /* Array terminated. */
666 );
667 
668 SHELL_CMD_REGISTER(gpio, &sub_gpio, "GPIO commands", NULL);
669