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 gpio_port_pins_t reserved_mask = GPIO_DT_RESERVED_RANGES_NGPIOS_SHELL(node_id); \
107 uint8_t line_names_len = DT_PROP_LEN_OR(node_id, gpio_line_names, 0); \
108 \
109 port_pin_get(reserved_mask, node_id##line_names, line_names_len, idx, entry); \
110 entry->subcmd = NULL; \
111 } \
112 \
113 SHELL_DYNAMIC_CMD_CREATE(node_id##sub_gpio_pin, node_id##cmd_gpio_pin_get);
114
115 #define IS_GPIO_CTRL_PIN_GET(node_id) \
116 COND_CODE_1(DT_PROP(node_id, gpio_controller), (GPIO_CTRL_PIN_GET_FN(node_id)), ())
117
118 DT_FOREACH_STATUS_OKAY_NODE(IS_GPIO_CTRL_PIN_GET)
119
120 #define GPIO_CTRL_LIST_ENTRY(node_id) \
121 { \
122 .dev = DEVICE_DT_GET(node_id), \
123 .ngpios = DT_PROP_OR(node_id, ngpios, NGPIOS_UNKNOWN), \
124 .reserved_mask = GPIO_DT_RESERVED_RANGES_NGPIOS_SHELL(node_id), \
125 .line_names = node_id##line_names, \
126 .line_names_len = DT_PROP_LEN_OR(node_id, gpio_line_names, 0), \
127 .subcmd = &node_id##sub_gpio_pin, \
128 },
129
130 #define IS_GPIO_CTRL_LIST(node_id) \
131 COND_CODE_1(DT_PROP(node_id, gpio_controller), (GPIO_CTRL_LIST_ENTRY(node_id)), ())
132
133 static const struct gpio_ctrl gpio_list[] = {DT_FOREACH_STATUS_OKAY_NODE(IS_GPIO_CTRL_LIST)};
134
get_gpio_ctrl(const char * name)135 static const struct gpio_ctrl *get_gpio_ctrl(const char *name)
136 {
137 size_t i;
138 const struct device *dev = shell_device_get_binding(name);
139
140 if (dev == NULL) {
141 return NULL;
142 }
143
144 for (i = 0; i < ARRAY_SIZE(gpio_list); i++) {
145 if (gpio_list[i].dev == dev) {
146 return &gpio_list[i];
147 }
148 }
149
150 return NULL;
151 }
152
line_cmp(const char * input,const char * line_name)153 static int line_cmp(const char *input, const char *line_name)
154 {
155 int i = 0;
156
157 while (true) {
158 if ((input[i] == '_') && (line_name[i] == ' ')) {
159 /* Allow input underscore to match line_name space */
160 } else if (input[i] != line_name[i]) {
161 return (input[i] > line_name[i]) ? 1 : -1;
162 } else if (line_name[i] == '\0') {
163 return 0;
164 }
165 i++;
166 }
167 }
168
get_gpio_pin(const struct shell * sh,const struct gpio_ctrl * ctrl,char * line_name)169 static int get_gpio_pin(const struct shell *sh, const struct gpio_ctrl *ctrl, char *line_name)
170 {
171 gpio_pin_t pin = PIN_NOT_FOUND;
172 gpio_pin_t i;
173 int result;
174
175 for (i = 0; i < ctrl->ngpios && i < ctrl->line_names_len; i++) {
176 result = line_cmp(line_name, ctrl->line_names[i]);
177 if (result == 0) {
178 if ((BIT64(i) & ctrl->reserved_mask) != 0) {
179 shell_error(sh, "Reserved pin");
180 return -EACCES;
181 } else if (pin == PIN_NOT_FOUND) {
182 pin = i;
183 } else {
184 shell_error(sh, "Line name ambiguous");
185 return -EFAULT;
186 }
187 }
188 }
189
190 if (pin == PIN_NOT_FOUND) {
191 shell_error(sh, "Line name not found: '%s'", line_name);
192 return -ENOENT;
193 }
194
195 return pin;
196 }
197
get_sh_gpio(const struct shell * sh,char ** argv,struct sh_gpio * gpio)198 static int get_sh_gpio(const struct shell *sh, char **argv, struct sh_gpio *gpio)
199 {
200 const struct gpio_ctrl *ctrl;
201 int ret = 0;
202 int pin;
203
204 ctrl = get_gpio_ctrl(argv[ARGV_DEV]);
205 if (ctrl == NULL) {
206 shell_error(sh, "unknown gpio controller: %s", argv[ARGV_DEV]);
207 return -EINVAL;
208 }
209 gpio->dev = ctrl->dev;
210 pin = shell_strtoul(argv[ARGV_PIN], 0, &ret);
211 if (ret != 0) {
212 pin = get_gpio_pin(sh, ctrl, argv[ARGV_PIN]);
213 if (pin < 0) {
214 return pin;
215 }
216 } else if ((BIT64(pin) & ctrl->reserved_mask) != 0) {
217 shell_error(sh, "Reserved pin");
218 return -EACCES;
219 }
220 gpio->pin = pin;
221
222 return 0;
223 }
224
cmd_gpio_conf(const struct shell * sh,size_t argc,char ** argv)225 static int cmd_gpio_conf(const struct shell *sh, size_t argc, char **argv)
226 {
227 gpio_flags_t flags = 0;
228 gpio_flags_t vendor_specific;
229 struct sh_gpio gpio;
230 int ret;
231 size_t len;
232
233 ret = get_sh_gpio(sh, argv, &gpio);
234 if (ret != 0) {
235 shell_help(sh);
236 return SHELL_CMD_HELP_PRINTED;
237 }
238
239 len = strlen(argv[ARGV_CONF]);
240 for (int i = 0; i < len; 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;
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;
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
gpio_device_name(const struct device * dev)477 static const char *gpio_device_name(const struct device *dev)
478 {
479 #ifdef CONFIG_DEVICE_DT_METADATA
480 const struct device_dt_nodelabels *nl = device_get_dt_nodelabels(dev);
481
482 if (nl != NULL && nl->num_nodelabels > 0) {
483 return nl->nodelabels[0];
484 }
485 #endif
486 return dev->name;
487 }
488
device_name_get(size_t idx,struct shell_static_entry * entry)489 static void device_name_get(size_t idx, struct shell_static_entry *entry)
490 {
491 const struct device *dev = gpio_list[idx].dev;
492
493 if (idx >= ARRAY_SIZE(gpio_list)) {
494 entry->syntax = NULL;
495 return;
496 }
497
498 entry->syntax = gpio_device_name(dev);
499 entry->handler = NULL;
500 entry->help = "Device";
501 entry->subcmd = gpio_list[idx].subcmd;
502 }
503
504 SHELL_DYNAMIC_CMD_CREATE(sub_gpio_dev, device_name_get);
505
506 struct pin_info {
507 const struct device *dev;
508 bool reserved;
509 gpio_pin_t pin;
510 const char *line_name;
511 };
512
513 struct pin_order_user_data {
514 const struct shell *sh;
515 struct pin_info prev;
516 struct pin_info next;
517 };
518
519 typedef void (*pin_foreach_func_t)(const struct pin_info *info, void *user_data);
520
print_gpio_ctrl_info(const struct shell * sh,const struct gpio_ctrl * ctrl)521 static void print_gpio_ctrl_info(const struct shell *sh, const struct gpio_ctrl *ctrl)
522 {
523 gpio_pin_t pin;
524 bool reserved;
525 const char *line_name;
526
527 shell_print(sh, " ngpios: %u", ctrl->ngpios);
528 shell_print(sh, " Reserved pin mask: 0x%08X\n", ctrl->reserved_mask);
529
530 shell_print(sh, " Reserved Pin Line Name");
531 for (pin = 0; pin < ctrl->ngpios; pin++) {
532 reserved = (BIT64(pin) & ctrl->reserved_mask) != 0;
533 if (pin < ctrl->line_names_len) {
534 line_name = ctrl->line_names[pin];
535 } else {
536 line_name = "";
537 }
538 shell_print(sh, " %c %2u %s", reserved ? '*' : ' ', pin, line_name);
539 }
540 }
541
foreach_pin(pin_foreach_func_t func,void * user_data)542 static void foreach_pin(pin_foreach_func_t func, void *user_data)
543 {
544 gpio_port_pins_t reserved_mask;
545 struct pin_info info;
546 gpio_pin_t pin;
547 size_t i;
548
549 for (i = 0; i < ARRAY_SIZE(gpio_list); i++) {
550 for (pin = 0; pin < gpio_list[i].ngpios; pin++) {
551 info.dev = gpio_list[i].dev;
552 reserved_mask = gpio_list[i].reserved_mask;
553 info.reserved = (BIT64(pin) & reserved_mask) != 0;
554 info.pin = pin;
555 if (pin < gpio_list[i].line_names_len) {
556 info.line_name = gpio_list[i].line_names[pin];
557 } else {
558 info.line_name = "";
559 }
560 func(&info, user_data);
561 }
562 }
563 }
564
pin_cmp(const struct pin_info * a,const struct pin_info * b)565 static int pin_cmp(const struct pin_info *a, const struct pin_info *b)
566 {
567 int result = strcmp(a->line_name, b->line_name);
568
569 if (result != 0) {
570 return result;
571 }
572 result = strcmp(a->dev->name, b->dev->name);
573 if (result != 0) {
574 return result;
575 }
576 result = (int)a->pin - (int)b->pin;
577
578 return result;
579 }
580
pin_get_next(const struct pin_info * info,void * user_data)581 static void pin_get_next(const struct pin_info *info, void *user_data)
582 {
583 struct pin_order_user_data *data = user_data;
584 int result;
585
586 if (data->prev.line_name != NULL) {
587 result = pin_cmp(info, &data->prev);
588 } else {
589 result = 1;
590 }
591 if (result > 0) {
592 if (data->next.line_name == NULL) {
593 data->next = *info;
594 return;
595 }
596 result = pin_cmp(info, &data->next);
597 if (result < 0) {
598 data->next = *info;
599 }
600 }
601 }
602
pin_ordered(const struct pin_info * info,void * user_data)603 static void pin_ordered(const struct pin_info *info, void *user_data)
604 {
605 struct pin_order_user_data *data = user_data;
606
607 ARG_UNUSED(info);
608
609 foreach_pin(pin_get_next, data);
610
611 shell_print(data->sh, " %-12s %-8c %-16s %2u",
612 data->next.line_name,
613 data->next.reserved ? '*' : ' ',
614 gpio_device_name(data->next.dev),
615 data->next.pin);
616
617 data->prev = data->next;
618 data->next.line_name = NULL;
619 }
620
print_ordered_info(const struct shell * sh)621 static void print_ordered_info(const struct shell *sh)
622 {
623 struct pin_order_user_data data = {0};
624
625 data.sh = sh;
626
627 shell_print(sh, " %-12s %-8s %-16s %-3s",
628 "Line", "Reserved", "Device", "Pin");
629
630 foreach_pin(pin_ordered, &data);
631 }
632
cmd_gpio_info(const struct shell * sh,size_t argc,char ** argv)633 static int cmd_gpio_info(const struct shell *sh, size_t argc, char **argv)
634 {
635 const struct gpio_ctrl *ctrl = get_gpio_ctrl(argv[ARGV_DEV]);
636
637 if (ctrl == NULL) {
638 /* No device specified */
639 print_ordered_info(sh);
640 return 0;
641 }
642
643 print_gpio_ctrl_info(sh, ctrl);
644
645 return 0;
646 }
647
648 SHELL_STATIC_SUBCMD_SET_CREATE(sub_gpio,
649 SHELL_CMD_ARG(conf, &sub_gpio_dev,
650 "Configure GPIO pin\n"
651 "Usage: gpio conf <device> <pin> <configuration <i|o>[u|d][h|l][0|1]> [vendor specific]\n"
652 "<i|o> - input|output\n"
653 "[u|d] - pull up|pull down, otherwise open\n"
654 "[h|l] - active high|active low, otherwise defaults to active high\n"
655 "[0|1] - initialise to logic 0|logic 1, otherwise defaults to logic 0\n"
656 "[vendor specific] - configuration flags within the mask 0xFF00\n"
657 " see include/zephyr/dt-bindings/gpio/",
658 cmd_gpio_conf, 4, 1),
659 SHELL_CMD_ARG(get, &sub_gpio_dev,
660 "Get GPIO pin value\n"
661 "Usage: gpio get <device> <pin>", cmd_gpio_get, 3, 0),
662 SHELL_CMD_ARG(set, &sub_gpio_dev,
663 "Set GPIO pin value\n"
664 "Usage: gpio set <device> <pin> <level 0|1>", cmd_gpio_set, 4, 0),
665 SHELL_COND_CMD_ARG(CONFIG_GPIO_SHELL_TOGGLE_CMD, toggle, &sub_gpio_dev,
666 "Toggle GPIO pin\n"
667 "Usage: gpio toggle <device> <pin>", cmd_gpio_toggle, 3, 0),
668 SHELL_CMD(devices, NULL,
669 "List all GPIO devices\n"
670 "Usage: gpio devices", cmd_gpio_devices),
671 SHELL_COND_CMD_ARG(CONFIG_GPIO_SHELL_BLINK_CMD, blink, &sub_gpio_dev,
672 "Blink GPIO pin\n"
673 "Usage: gpio blink <device> <pin>", cmd_gpio_blink, 3, 0),
674 SHELL_COND_CMD_ARG(CONFIG_GPIO_SHELL_INFO_CMD, info, &sub_gpio_dev,
675 "GPIO Information\n"
676 "Usage: gpio info [device]", cmd_gpio_info, 1, 1),
677 SHELL_SUBCMD_SET_END /* Array terminated. */
678 );
679
680 SHELL_CMD_REGISTER(gpio, &sub_gpio, "GPIO commands", NULL);
681